<commit_before>#include "music.h"
#include <string>
#include <iostream>
#include "globals.h"
#include <algorithm>
// #include "defs.h"

#include "configuration.h"
#include "thread.h"
#include "funcs.h"
#include "file-system.h"
#include "music-player.h"

using namespace std;

static Music * instance = NULL;

static double volume = 1.0;
// static bool muted = false;
static Util::Thread::Id musicThread;
static Util::Thread::Lock musicMutex;
static bool alive = true;

static void * playMusic( void * );

#define synchronized for( int __l( ! Util::Thread::acquireLock(&musicMutex)); __l; __l = 0, Util::Thread::releaseLock(&musicMutex) )

#define LOCK Util::Thread::acquireLock(&musicMutex);
#define UNLOCK Util::Thread::releaseLock(&musicMutex);

/*
#undef LOCK
#undef UNLOCK
#define LOCK
#define UNLOCK
*/

static void * bogus_thread( void * x){
	return NULL;
}

Music::Music(bool on):
playing(false),
enabled(on),
fading(0),
musicPlayer(NULL),
currentSong(""){

    if (instance != NULL){
        cerr << "Trying to instantiate music object twice!" << endl;
        return;
    }

    volume = (double) Configuration::getMusicVolume() / 100.0;

    instance = this;

    Util::Thread::initializeLock(&musicMutex);
    Global::debug(1) << "Creating music thread" << endl;
    if (on){
        Util::Thread::createThread(&musicThread, NULL, (Util::Thread::ThreadFunction) playMusic, (void *)instance);
    } else {
        /* FIXME: just don't create a thread at all.. */
        Util::Thread::createThread(&musicThread, NULL, (Util::Thread::ThreadFunction) bogus_thread, NULL);
    }
}

/*
static bool isAlive(){
	bool f = false;
	synchronized{
		f = alive;
	}
	return f;
}
*/

static void * playMusic( void * _music ){
    Music * music = (Music *) _music;

    Global::debug(1) << "Playing music" << endl;

    /*
       unsigned int tick = 0;
       unsigned int counter;
       */

    bool playing = true;
    while (playing){
        LOCK;{
            playing = alive;
            music->doPlay();
        }
        UNLOCK;
        Util::rest(10);

        // Util::YIELD();
        // pthread_yield();
    }

    // cout << "Done with music thread" << endl;

    return NULL;
}

double Music::getVolume(){
    double vol = 0;
    LOCK;{
        vol = volume;
    }
    UNLOCK;
    return vol;
}

void Music::doPlay(){
    if (this->playing){
        double f = fading / 500.0;
        switch (fading){
            case -1: {
                if (volume + f < 0){
                    fading = 0;
                    volume = 0;
                } else {
                    volume += f;
                    this->_setVolume(volume);
                }
                break;
            }
            case 1: {
                if (volume + f > 1.0){
                    fading = 0;
                    volume = 1.0;
                } else {
                    volume += f;
                    this->_setVolume(volume);
                }
                break;
            }
        }
        musicPlayer->poll();
    }
}

/*
Music::Music( const char * song ):
volume( 1.0 ),
muted( false ),
player( NULL ),
music_file( NULL ){

	loadSong( song );

}

Music::Music( const string & song ):
volume( 1.0 ),
muted( false ),
player( NULL ),
music_file( NULL ){
	loadSong( song );
}
*/

void Music::fadeIn(double vol){
    LOCK;{
        // volume = vol;
        instance->_fadeIn();
    }
    UNLOCK;
}

void Music::fadeOut( double vol ){
    LOCK;{
        // volume = vol;
        instance->_fadeOut();
    }
    UNLOCK;
}

/* FIXME */
void Music::_fadeIn(){
    // fading = 1;
}

void Music::_fadeOut(){
    // fading = -1;
}

bool Music::loadSong( const char * song ){
    bool loaded = false;
    LOCK;{
        if (instance != NULL){
            loaded = instance->internal_loadSong(song);
        }
    }
    UNLOCK;
    return loaded;
    // muted = false;
}

/* remove an element from a vector at index 'pos' and return it */
template< class Tx_ >
static Tx_ removeVectorElement( vector< Tx_ > & toRemove, int pos ){
    int count = 0;
    typename vector< Tx_ >::iterator it;
    for ( it = toRemove.begin(); it != toRemove.end() && count < pos; count++, it++ );

    if ( it == toRemove.end() ){
        /* this isnt right, but whatever */
        return toRemove.front();
    }

    Tx_ removed = toRemove[pos];
    toRemove.erase(it);
    return removed;

}
	
void Music::loadSong(vector<Filesystem::AbsolutePath> songs){

    /*
       cout << "Songs = " << &Songs << endl;
       if ( ! loadSong( "music/song5.xm" ) ){
       cerr << "Could not load music/song5.xm" << endl;
       }
       return;
       */

    /*
    vector<Filesystem::AbsolutePath> _songs = Songs;
    vector<Filesystem::AbsolutePath> songs;
    while ( ! _songs.empty() ){
        int i = Util::rnd(_songs.size());
        songs.push_back(removeVectorElement(_songs, i));
    }
    */

    /*
       songs.clear();
       songs.push_back( "music/song3.xm" );
       */

    std::random_shuffle(songs.begin(), songs.end());
    for (vector<Filesystem::AbsolutePath>::iterator it = songs.begin(); it != songs.end(); it++){
        Global::debug(1) << "Trying to load song " << (*it).path() << endl;
        if (loadSong((*it).path())){
            break;
        }
    }
}

bool Music::loadSong( const string & song ){
    return loadSong( song.c_str() );
}

void Music::_play(){
    if (playing == false && musicPlayer != NULL){
        musicPlayer->play();
        playing = true;
    }
}

void Music::play(){
    LOCK;{
        instance->_play();
    }
    UNLOCK;
}

void Music::_pause(){
    playing = false;
    if (musicPlayer != NULL){
        musicPlayer->pause();
    }
}

void Music::pause(){
    LOCK;{
        instance->_pause();
    }
    UNLOCK;
}

void Music::soften(){
    LOCK;{
        instance->_soften();
    }
    UNLOCK;
}

void Music::_soften(){
    if (volume > 0.1){
        volume -= 0.1;
    } else {
        volume = 0.0;
    }

    _setVolume(volume);
}

void Music::louden(){
    LOCK;{
        instance->_louden();
    }
    UNLOCK;
}

void Music::_louden(){
    if ( volume < 0.9 ){
        volume += 0.1;
    } else {
        volume = 1.0;
    }

    _setVolume(volume);
}

void Music::mute(){
    setVolume(0);
}

void Music::setVolume( double vol ){

    LOCK;{
        volume = vol;
        if ( volume > 1.0 ){
            volume = 1.0;
        }
        if ( volume < 0 ){
            volume = 0;
        }
        instance->_setVolume( volume );
    }
    UNLOCK;
}

void Music::_setVolume(double vol){
    if (musicPlayer){
        musicPlayer->setVolume(vol);
    }
}
	
Music::~Music(){

    LOCK;{
        if (musicPlayer){
            delete musicPlayer;
        }

        alive = false;
        playing = false;
    }
    UNLOCK;

    Global::debug( 1 ) << "Waiting for music thread to die" << endl;
    Util::Thread::joinThread(musicThread);

}

static string getExtension(const char * path_){
    string path(path_);
    if (path.rfind('.') != string::npos){
        return Util::lowerCaseAll(path.substr(path.rfind('.') + 1));
    }
    return "";
}

/* true if the file extension is something DUMB will probably recognize */
static bool isDumbFile(const char * path){
    string extension = getExtension(path);
    return extension == "mod" ||
           extension == "s3m" ||
           extension == "it" ||
           extension == "xm";
}

static bool isGMEFile(const char * path){
    string extension = getExtension(path);
    return extension == "nsf" ||
           extension == "spc" ||
           extension == "gym";
}

static bool isOggFile(const char * path){
    string extension = getExtension(path);
    return extension == "ogg";
}

static bool isMp3File(const char * path){
    string extension = getExtension(path);
    return extension == "mp3";
}

bool Music::internal_loadSong( const char * path ){
    if (!enabled){
        return false;
    }

    // cout << "Trying to load '" << path << "'" << endl;

    // Check current song and/or set it
    if (currentSong.compare(std::string(path))==0){
        return true;
    } else {
        currentSong = std::string(path);
    }

    if (musicPlayer != NULL){
        delete musicPlayer;
        musicPlayer = NULL;
    }
    try {
        if (isDumbFile(path)){
            musicPlayer = new Util::DumbPlayer(path);
            musicPlayer->play();
            playing = true;
        } else if (isGMEFile(path)){
            musicPlayer = new Util::GMEPlayer(path);
            musicPlayer->play();
            playing = true;
#ifdef HAVE_OGG
        } else if (isOggFile(path)){
            musicPlayer = new Util::OggPlayer(path);
            musicPlayer->play();
            playing = true;
#endif

#if defined(HAVE_MP3_MPG123) || defined(HAVE_MP3_MAD)
	} else if (isMp3File(path)){
	    /* Utilize SDL mixer to handle mp3 */
	    musicPlayer = new Util::Mp3Player(path);
	    musicPlayer->play();
	    playing = true;
#endif
        } else {
            return false;
        }
        if (musicPlayer != NULL){
            musicPlayer->setVolume(volume);
        }
    } catch (const Exception::Base & ex){
        Global::debug(0) << "Could not open music file '" << path << "' because " << ex.getTrace() << endl;
        //! FIXME Change from Base exception in the futer
        return false;
    }

    return true;
}

void Music::changeSong(){
    pause();
    fadeIn(0.3);
    loadSong(Filesystem::getFiles(Filesystem::find(Filesystem::RelativePath("music/")), "*"));
    play();
}

#undef synchronized
#undef LOCK
#undef UNLOCK
<commit_msg>check if music player exists<commit_after>#include "music.h"
#include <string>
#include <iostream>
#include "globals.h"
#include <algorithm>
// #include "defs.h"

#include "configuration.h"
#include "thread.h"
#include "funcs.h"
#include "file-system.h"
#include "music-player.h"

using namespace std;

static Music * instance = NULL;

static double volume = 1.0;
// static bool muted = false;
static Util::Thread::Id musicThread;
static Util::Thread::Lock musicMutex;
static bool alive = true;

static void * playMusic( void * );

#define synchronized for( int __l( ! Util::Thread::acquireLock(&musicMutex)); __l; __l = 0, Util::Thread::releaseLock(&musicMutex) )

#define LOCK Util::Thread::acquireLock(&musicMutex);
#define UNLOCK Util::Thread::releaseLock(&musicMutex);

/*
#undef LOCK
#undef UNLOCK
#define LOCK
#define UNLOCK
*/

static void * bogus_thread( void * x){
	return NULL;
}

Music::Music(bool on):
playing(false),
enabled(on),
fading(0),
musicPlayer(NULL),
currentSong(""){

    if (instance != NULL){
        cerr << "Trying to instantiate music object twice!" << endl;
        return;
    }

    volume = (double) Configuration::getMusicVolume() / 100.0;

    instance = this;

    Util::Thread::initializeLock(&musicMutex);
    Global::debug(1) << "Creating music thread" << endl;
    if (on){
        Util::Thread::createThread(&musicThread, NULL, (Util::Thread::ThreadFunction) playMusic, (void *)instance);
    } else {
        /* FIXME: just don't create a thread at all.. */
        Util::Thread::createThread(&musicThread, NULL, (Util::Thread::ThreadFunction) bogus_thread, NULL);
    }
}

/*
static bool isAlive(){
	bool f = false;
	synchronized{
		f = alive;
	}
	return f;
}
*/

static void * playMusic( void * _music ){
    Music * music = (Music *) _music;

    Global::debug(1) << "Playing music" << endl;

    /*
       unsigned int tick = 0;
       unsigned int counter;
       */

    bool playing = true;
    while (playing){
        LOCK;{
            playing = alive;
            music->doPlay();
        }
        UNLOCK;
        Util::rest(10);

        // Util::YIELD();
        // pthread_yield();
    }

    // cout << "Done with music thread" << endl;

    return NULL;
}

double Music::getVolume(){
    double vol = 0;
    LOCK;{
        vol = volume;
    }
    UNLOCK;
    return vol;
}

void Music::doPlay(){
    if (this->playing){
        double f = fading / 500.0;
        switch (fading){
            case -1: {
                if (volume + f < 0){
                    fading = 0;
                    volume = 0;
                } else {
                    volume += f;
                    this->_setVolume(volume);
                }
                break;
            }
            case 1: {
                if (volume + f > 1.0){
                    fading = 0;
                    volume = 1.0;
                } else {
                    volume += f;
                    this->_setVolume(volume);
                }
                break;
            }
        }
        if (musicPlayer != NULL){
            musicPlayer->poll();
        }
    }
}

/*
Music::Music( const char * song ):
volume( 1.0 ),
muted( false ),
player( NULL ),
music_file( NULL ){

	loadSong( song );

}

Music::Music( const string & song ):
volume( 1.0 ),
muted( false ),
player( NULL ),
music_file( NULL ){
	loadSong( song );
}
*/

void Music::fadeIn(double vol){
    LOCK;{
        // volume = vol;
        instance->_fadeIn();
    }
    UNLOCK;
}

void Music::fadeOut( double vol ){
    LOCK;{
        // volume = vol;
        instance->_fadeOut();
    }
    UNLOCK;
}

/* FIXME */
void Music::_fadeIn(){
    // fading = 1;
}

void Music::_fadeOut(){
    // fading = -1;
}

bool Music::loadSong( const char * song ){
    bool loaded = false;
    LOCK;{
        if (instance != NULL){
            loaded = instance->internal_loadSong(song);
        }
    }
    UNLOCK;
    return loaded;
    // muted = false;
}

/* remove an element from a vector at index 'pos' and return it */
template< class Tx_ >
static Tx_ removeVectorElement( vector< Tx_ > & toRemove, int pos ){
    int count = 0;
    typename vector< Tx_ >::iterator it;
    for ( it = toRemove.begin(); it != toRemove.end() && count < pos; count++, it++ );

    if ( it == toRemove.end() ){
        /* this isnt right, but whatever */
        return toRemove.front();
    }

    Tx_ removed = toRemove[pos];
    toRemove.erase(it);
    return removed;

}
	
void Music::loadSong(vector<Filesystem::AbsolutePath> songs){

    /*
       cout << "Songs = " << &Songs << endl;
       if ( ! loadSong( "music/song5.xm" ) ){
       cerr << "Could not load music/song5.xm" << endl;
       }
       return;
       */

    /*
    vector<Filesystem::AbsolutePath> _songs = Songs;
    vector<Filesystem::AbsolutePath> songs;
    while ( ! _songs.empty() ){
        int i = Util::rnd(_songs.size());
        songs.push_back(removeVectorElement(_songs, i));
    }
    */

    /*
       songs.clear();
       songs.push_back( "music/song3.xm" );
       */

    std::random_shuffle(songs.begin(), songs.end());
    for (vector<Filesystem::AbsolutePath>::iterator it = songs.begin(); it != songs.end(); it++){
        Global::debug(1) << "Trying to load song " << (*it).path() << endl;
        if (loadSong((*it).path())){
            break;
        }
    }
}

bool Music::loadSong( const string & song ){
    return loadSong( song.c_str() );
}

void Music::_play(){
    if (playing == false && musicPlayer != NULL){
        musicPlayer->play();
        playing = true;
    }
}

void Music::play(){
    LOCK;{
        instance->_play();
    }
    UNLOCK;
}

void Music::_pause(){
    playing = false;
    if (musicPlayer != NULL){
        musicPlayer->pause();
    }
}

void Music::pause(){
    LOCK;{
        instance->_pause();
    }
    UNLOCK;
}

void Music::soften(){
    LOCK;{
        instance->_soften();
    }
    UNLOCK;
}

void Music::_soften(){
    if (volume > 0.1){
        volume -= 0.1;
    } else {
        volume = 0.0;
    }

    _setVolume(volume);
}

void Music::louden(){
    LOCK;{
        instance->_louden();
    }
    UNLOCK;
}

void Music::_louden(){
    if ( volume < 0.9 ){
        volume += 0.1;
    } else {
        volume = 1.0;
    }

    _setVolume(volume);
}

void Music::mute(){
    setVolume(0);
}

void Music::setVolume( double vol ){

    LOCK;{
        volume = vol;
        if ( volume > 1.0 ){
            volume = 1.0;
        }
        if ( volume < 0 ){
            volume = 0;
        }
        instance->_setVolume( volume );
    }
    UNLOCK;
}

void Music::_setVolume(double vol){
    if (musicPlayer){
        musicPlayer->setVolume(vol);
    }
}
	
Music::~Music(){

    LOCK;{
        if (musicPlayer){
            delete musicPlayer;
        }

        alive = false;
        playing = false;
    }
    UNLOCK;

    Global::debug( 1 ) << "Waiting for music thread to die" << endl;
    Util::Thread::joinThread(musicThread);

}

static string getExtension(const char * path_){
    string path(path_);
    if (path.rfind('.') != string::npos){
        return Util::lowerCaseAll(path.substr(path.rfind('.') + 1));
    }
    return "";
}

/* true if the file extension is something DUMB will probably recognize */
static bool isDumbFile(const char * path){
    string extension = getExtension(path);
    return extension == "mod" ||
           extension == "s3m" ||
           extension == "it" ||
           extension == "xm";
}

static bool isGMEFile(const char * path){
    string extension = getExtension(path);
    return extension == "nsf" ||
           extension == "spc" ||
           extension == "gym";
}

static bool isOggFile(const char * path){
    string extension = getExtension(path);
    return extension == "ogg";
}

static bool isMp3File(const char * path){
    string extension = getExtension(path);
    return extension == "mp3";
}

bool Music::internal_loadSong( const char * path ){
    if (!enabled){
        return false;
    }

    // cout << "Trying to load '" << path << "'" << endl;

    // Check current song and/or set it
    if (currentSong.compare(std::string(path))==0){
        return true;
    } else {
        currentSong = std::string(path);
    }

    if (musicPlayer != NULL){
        delete musicPlayer;
        musicPlayer = NULL;
    }
    try {
        if (isDumbFile(path)){
            musicPlayer = new Util::DumbPlayer(path);
            musicPlayer->play();
            playing = true;
        } else if (isGMEFile(path)){
            musicPlayer = new Util::GMEPlayer(path);
            musicPlayer->play();
            playing = true;
#ifdef HAVE_OGG
        } else if (isOggFile(path)){
            musicPlayer = new Util::OggPlayer(path);
            musicPlayer->play();
            playing = true;
#endif

#if defined(HAVE_MP3_MPG123) || defined(HAVE_MP3_MAD)
	} else if (isMp3File(path)){
	    /* Utilize SDL mixer to handle mp3 */
	    musicPlayer = new Util::Mp3Player(path);
	    musicPlayer->play();
	    playing = true;
#endif
        } else {
            return false;
        }
        if (musicPlayer != NULL){
            musicPlayer->setVolume(volume);
        }
    } catch (const Exception::Base & ex){
        Global::debug(0) << "Could not open music file '" << path << "' because " << ex.getTrace() << endl;
        //! FIXME Change from Base exception in the futer
        return false;
    }

    return true;
}

void Music::changeSong(){
    pause();
    fadeIn(0.3);
    loadSong(Filesystem::getFiles(Filesystem::find(Filesystem::RelativePath("music/")), "*"));
    play();
}

#undef synchronized
#undef LOCK
#undef UNLOCK

{'fraction_non_alphanumeric': 0.15162417227175556, 'fraction_numerical': 0.00782105427811669, 'mean_word_length': 2.1298955613577024, 'pattern_counts': {'":': 0, '<': 139, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2180324', 'n_tokens_mistral': 6270, 'n_tokens_neox': 5974, 'n_words': 1497}