/** ****************************************************************************** @file /common/rm/rmsound.cpp @brief RM pristupujici ke zvukum @author Vta @version 1.0 ******************************************************************************/ #include "common/rm/rmsound.h" #include "common/utils.h" namespace rm { void TRM_sound::loadData(int id) { this->loadSound(id); } /// Pomocny buffer static char bu_file[K8_MAX_FILE_NAME_LEN]; /// Pomocny buffer static char bu_path[K8_MAX_PATH_LEN]; #define bu_typesize 10 ///< velikost typu /// Pomocny buffer static char bu_type[bu_typesize]; void TRM_sound::loadSound(int id) { this->lock(); int playlist; if ((*(this->sounds))[id]==NULL) // pokud TSound jeste nebyl vytvoren { (*(this->sounds))[id]=(TSound*)KMemAlloc(sizeof(TSound)); if ((this->index->getData(bu_type,bu_typesize,"sound",id,"type",0,NULL)==XML_ERROR_NO_SUCH_A_PATH) || (this->index->getData(bu_file,K8_MAX_FILE_NAME_LEN,"sound",id,"file",0,NULL)==XML_ERROR_NO_SUCH_A_PATH) || ((playlist=this->index->getDataInt("sound",id,"playlist",0,NULL))==XML_ERROR_NO_SUCH_A_PATH) ) { this->unlock(); GLOBALLOGID(PRIORITY_FATAL, "RMsound can not load the sound having id=%i",id); THROW(E_8K_RM,"RMsound can not load a sound"); } (*this->sounds)[id]->playlist=playlist; // priradim typ if (strcmp(bu_type,SOUND_MUSIC)==0) { // strpath(&path,RESOURCES_DIR,this->rmconfi->getPack(),MUSICS_DIR,file,pathsize,""); // pripona je v xml file // (*this->sounds)[id]->data=Mix_LoadMUS(path); // MUS NELZE NAHRAT DOPREDU (*this->sounds)[id]->type=SOUND_MUSIC_CODE; } else { if (strcmp(bu_type,SOUND_SAMPLE)==0) { // TProfile * profile = (*profiles)[lastprof]; #if (MULTILANGUAGE_VOICES==1) int language=this->rmconfi->getDefaultLanguage(); char * code=NULL; size_t size=0; this->rmtxti->getLangCode(&code,size,language); strpartpath(bu_path,RESOURCES_DIR,this->rmconfi->getPack(),SAMPLES_DIR,code,K8_MAX_PATH_LEN-30,""); // pripona je v xml file strcat(bu_path,"/"); strncat(bu_path,bu_file,25); if ((size>0) && (code!=NULL)) KMemFree(code); #ifndef _K_EDITOR_ (*this->sounds)[id]->data=Mix_LoadWAV(bu_path); #endif (*this->sounds)[id]->type=SOUND_SAMPLE_CODE; if ((*this->sounds)[id]->data==NULL) // the requested sound does not exists in the selected language { strpartpath(bu_path,RESOURCES_DIR,this->rmconfi->getPack(),SAMPLES_DIR,bu_file,K8_MAX_PATH_LEN-30,""); // pripona je v xml file #ifndef _K_EDITOR_ (*this->sounds)[id]->data=Mix_LoadWAV(bu_path); #endif } #else strpartpath(bu_path,RESOURCES_DIR,this->rmconfi->getPack(),SAMPLES_DIR,bu_file,K8_MAX_PATH_LEN,""); // pripona je v xml file #ifndef _K_EDITOR_ (*this->sounds)[id]->data=Mix_LoadWAV(bu_path); if ((*this->sounds)[id]->data==NULL) { GLOBALLOGID(PRIORITY_FATAL, "RMsound can not load the sound having id=%i",id); THROW(E_8K_RM,"RMsound can not load a sound"); } #endif (*this->sounds)[id]->type=SOUND_SAMPLE_CODE; #endif } } (*this->sounds)[id]->id=id; this->writeGroup(id); } this->unlock(); } void TRM_sound::delSound(int id) { this->lock(); char type[10]; int typesize=10; this->index->getData(type,typesize,"sound",id,"type",0,NULL); this->index->delData(0,"sound",id,NULL); if (this->saveToFile(this->rmconfi->getPack(),this->rmconfi->getSoundFile())!=XML_ERROR_OK) // zapisu index do souboru { this->unlock(); GLOBALLOGID(PRIORITY_FATAL, "RMsound can not write to the index file"); THROW(E_8K_RM,"RMsound can not write to the index file"); } if ((*(this->sounds))[id]!=NULL) // odstanim i z pameti { this->freeData(id); } this->unlock(); } int TRM_sound::addSound(int newid,char *filename,int type) { return 0; } /// Pomocny buffer static char bu_file2[K8_MAX_FILE_NAME_LEN]; /// Pomocny buffer static char bu_path2[K8_MAX_PATH_LEN]; TSound * TRM_sound::getSound(int id) { this->lock(); if ( ((*(this->sounds))[id]==NULL) ) { GLOBALLOGID(PRIORITY_FATAL, "RMsound the sound having id %i has not been loaded yet",id); THROW(E_8K_RM,"RMsound can not access a sound before loading"); } if ((*this->sounds)[id]->type==SOUND_MUSIC_CODE) // hudba se nacita az ve chvili kdy o ni pozadam (kvuli chybe v knihovne SDL_mixer) { if (this->lastMusId>0) { #ifndef _K_EDITOR_ Mix_FreeMusic((Mix_Music*)(*this->sounds)[this->lastMusId]->data); #endif } this->lastMusId=id; if (this->index->getData(bu_file2,K8_MAX_FILE_NAME_LEN,"sound",id,"file",0,NULL)==XML_ERROR_NO_SUCH_A_PATH) { this->unlock(); GLOBALLOGID(PRIORITY_FATAL, "RMsound can not load the music having %i",id); THROW(E_8K_RM,"RMsound can not load a music"); } strpartpath(bu_path2,RESOURCES_DIR,this->rmconfi->getPack(),MUSICS_DIR,bu_file2,K8_MAX_PATH_LEN,""); #ifndef _K_EDITOR_ (*this->sounds)[id]->data=Mix_LoadMUS(bu_path2); #endif } this->unlock(); return (*(this->sounds))[id]; } int TRM_sound::getMaxId() { this->lock(); int maxindex; if (this->sounds->getMaxId()>this->index->getMaxId()) maxindex=this->sounds->getMaxId(); else maxindex=this->index->getMaxId(); this->unlock(); return maxindex; } void TRM_sound::freeData(int id) { this->freeSound(id); } void TRM_sound::freeSound(int id) { this->lock(); if ((*(this->sounds))[id]!=NULL) { if ((*(this->sounds))[id]->data!=NULL) // odstanim i z pameti { if ((*(this->sounds))[id]->type==SOUND_SAMPLE_CODE) { #ifndef _K_EDITOR_ Mix_FreeChunk((Mix_Chunk *)(*this->sounds)[id]->data); #endif } else { if ((*(this->sounds))[id]->type==SOUND_MUSIC_CODE) { if (id==this->lastMusId) // pouze tento mohl byt zrovna nacten a neodstranen { #ifndef _K_EDITOR_ Mix_FreeMusic((Mix_Music *)(*this->sounds)[id]->data); #endif this->lastMusId=0; } } } KMemFree((*(this->sounds))[id]); (*(this->sounds))[id]=NULL; } } else { this->unlock(); GLOBALLOGID(PRIORITY_FATAL, "RMsound can not released object having id %i",id); THROW(E_8K_RM,"RMsound can not release data which has not been loaded yet"); } this->unlock(); } int TRM_sound::getSounds(DA ** snds) { this->lock(); *snds=this->sounds; this->unlock(); return this->sounds->getMaxId(); } int TRM_sound::getSoundsCount() { this->lock(); int num=this->index->getMaxId(); this->unlock(); return num; } int TRM_sound::getSoundsLoaded() { this->lock(); int num=0; int j; for (j=this->sounds->getNext(-1);j!=-1;j=this->sounds->getNext(j)) { num++; } this->unlock(); return num; } void TRM_sound::playMusic(int playlist) { this->lock(); this->playingGroup=playlist; if (this->playingGroup>0) { int j=-1; for (j=this->sounds->getNext(-1);j!=-1;j=this->sounds->getNext(j)) { if ( ((*(this->sounds))[j]->type==SOUND_MUSIC_CODE) && ((*(this->sounds))[j]->playlist==this->playingGroup) ) break; } if (j!=-1) { // If we just rely on start playing in thread e.g. in main menu there will be silent delay after the application runs TSound * first=this->getSound(j); Mix_PlayMusic((Mix_Music *)first->data, 1); } else { Mix_HaltMusic(); this->playingGroup=0; } } else { if (this->playingGroup==0) { Mix_HaltMusic(); } else { Mix_FadeOutMusic(-(this->playingGroup)); } this->playingGroup=0; } this->unlock(); } TRM_sound::TRM_sound(TRM_conf_i * rmc,TRM_txt_i * rmt) // konstruktor nema smyl zamykat... { this->rmtxti=rmt; this->playingGroup=0; this->rmconfi=rmc; this->lastMusId=0; this->group=0; this->sounds=new DA; this->sem=SDL_CreateSemaphore(0); this->checkMusicPlaying=SDL_CreateThread(checkMusicPlaying_thread, (void*)this); SDL_SemWait(this->sem); SDL_DestroySemaphore(this->sem); this->status=STATUS_PREPARE; int retvalue; try { strpartpath(bu_path,RESOURCES_DIR,this->rmconfi->getPack(),XML_DIR,this->rmconfi->getSoundFile(),K8_MAX_FILE_NAME_LEN,".xml"); } catch (E_8K_RM) { GLOBALLOGID(PRIORITY_FATAL, "files.xml is corrupted"); THROW(E_8K_RM,"files.xml is corrupted"); } retvalue=this->readInfoFile(bu_path); // do RMtxt nactu informace kde ma hledat vsechny sound if (retvalue!=XML_ERROR_OK) // chyba pri cteni fajlu o jazycich { GLOBALLOGID(PRIORITY_MISSING_FILE,"RMsound the file %s is corrupted",bu_path); THROW(E_8K_RM,"RMsound The index file is corrupted"); } GLOBALLOGID(PRIORITY_CONFIRM ,"RMsound was created"); } TRM_sound::~TRM_sound() { this->status=STATUS_ENDING; SDL_WaitThread(this->checkMusicPlaying,NULL); delete this->rmtxti; delete this->rmconfi; int j; for (j=this->sounds->getNext(-1);j!=-1;j=this->sounds->getNext(j)) { this->freeData(j); } delete this->sounds; GLOBALLOGID(PRIORITY_CONFIRM ,"RMsound was destroyed"); } int checkMusicPlaying_thread(void * data) { TRM_sound* that=(TRM_sound*) data; int j; TSound * music; try { SDL_SemPost(that->sem); while (1) { if (that->status==STATUS_ENDING) { return 0; } // check the music fade status that->lock(); switch(Mix_FadingMusic()) { // it can be silent iff its not fanding case MIX_NO_FADING: if (Mix_PlayingMusic()==0) { if (that->playingGroup>0) { for (j=that->sounds->getNext(that->lastMusId);j!=-1;j=that->sounds->getNext(j)) { if ( ((*(that->sounds))[j]->type==SOUND_MUSIC_CODE) && ((*(that->sounds))[j]->playlist==that->playingGroup) ) break; } if (j<=0) // if not found check the rest... it could be tested that -1lastMusId { for (j=that->sounds->getNext(-1);j!=-1;j=that->sounds->getNext(j)) { if ( ((*(that->sounds))[j]->type==SOUND_MUSIC_CODE) && ((*(that->sounds))[j]->playlist==that->playingGroup) ) break; } } if (j>0) { music=that->getSound(j); Mix_PlayMusic((Mix_Music *)music->data, 1); } else { Mix_HaltMusic(); that->playingGroup=0; } } } break; /*/ case MIX_FADING_OUT: printf("Fading out music.\n"); break; case MIX_FADING_IN: printf("Fading in music.\n"); break; */ } that->unlock(); SDL_Delay(3000); } } catch (E_8K &e) { GLOBALLOGID(PRIORITY_EXCETION_IN_THREAD, "Exception in checkMusicPlaying_thread"); if (that->status!=STATUS_ENDING) KSendMessage(RQUEUE,MSG_EXCEPTION_IN_THREAD,MOD_NET,BROADCAST,&e); } return 0; } } // namespace