thread für playback und gui
-
Hi,
ich habe mir einen kleine player auf basis von nmm gebaut. Wie man unte im quellcode sieht lasse ich den player solange laufen wie die schleifen bedingung erfüllt ist. Die Schleife brauche ich sonst würde er nicht spielen sondern sofort wieder aus der funktion gehen.
Das Problem ist nun, dass mein Gui einfriert wenn der player läuft.
void *PlayerGB::play(void*) { NamedObject::getGlobalInstance().setErrorStream(0, NamedObject::ALL_LEVELS); NamedObject::getGlobalInstance().setWarningStream(0, NamedObject::ALL_LEVELS); NamedObject::getGlobalInstance().setMessageStream(0, NamedObject::ALL_LEVELS); NamedObject::getGlobalInstance().setDebugStream(0, NamedObject::ALL_LEVELS); NMMApplication* app = 0; try { app = ProxyApplication::getApplication(0, 0); NodeDescription playback_nd("PlaybackNode"); NodeDescription display_nd("XDisplayNode"); playback_nd.setLocation("il076"); display_nd.setLocation("il076"); MultiAudioVideoSynchronizer av_sync; IMultiAudioVideoSynchronizer_var sync(av_sync.getCheckedInterface<IMultiAudioVideoSynchronizer>()); GraphBuilder2 gb; if(!gb.setURL("file:///home/kupfertm/music/3tagebart.wav")) { throw Exception("Invalid URL given"); } gb.setMultiAudioVideoSynchronizer(sync.get()); gb.setAudioSink(playback_nd); gb.setVideoSink(display_nd); m_composite = gb.createGraph(*app); m_composite->reachStarted(); m_appState = PlayerGB::PLAY; while(m_appState == PlayerGB::PLAY) { sleep(10); } } catch (const Exception& e) { cerr << e << endl; } catch(...) { cerr << "something went wrong..." << endl; } return(0); }
Meine Idee war nun das Playback in einem thread laufen zu lassen.
in der Hoffnung, dass der Player dann nichtmehr einfriert. Sobalt sich das Flag m_appstate ändert sollte die schleife abbrechen.
Leider Funktioniert das nicht.Was kann man da machen?
Muss ich das Gui auch in einen extra Thread packen?grüße
-
void *PlayerGB::play(void*)
haben die void* einen sinn?
-
m_appState = PlayerGB::PLAY; while(m_appState == PlayerGB::PLAY) { sleep(10); }
Ich hoffe du hast das im Multithreaded Code nicht ebenfalls so gemacht. Der Compiler macht dir daraus gerne:
start: sleep(10); goto start;
Der Compiler weiss ja nicht, dass sich m_appState irgendwann irgendwie ändert. Du musst hier Synchronisationsprimitive benutzen. Am einfachsten geht es mit Mutexen. Hier ist aber eine Condition Variable eher angebracht:
pthread_mutex_lock(&app_state_mutex); while (m_appState == PlayerGB::PLAY) { pthread_cond_wait(¬_playing_cond, &app_state_mutex); } pthread_mutex_unlock(&app_state_mutex);
Und auf keinen Fall die while Schleife hier vergessen, da ein pthread_cond_wait zurückkehren kann, ohne, dass die Bedingung erfüllt ist.
-
hi, thx für eure antworten
ja die ganzen void haben eine bewandnis, hier die definition von pthread_create
int pthread_create(pthread_t *restrict thread,
const pthread_attr_t *restrict attr,
void *(*start_routine)(void*), void *restrict arg);----------------------------------------------------------------------------
leider funktioniert der player noch nicht das gui friert immernoch ein
ich habe folgendes probiertpthread_mutex_t m_appState_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t not_playing_cond = PTHREAD_COND_INITIALIZER;
bin mir nicht sicher ob die werte so richtig sind
pthread_mutex_lock(&m_appState_mutex); m_appState = PlayerGB::PLAY; while(m_appState == PlayerGB::PLAY) { pthread_cond_wait(¬_playing_cond, &m_appState_mutex); } pthread_mutex_unlock(&m_appState_mutex);
ich habe wohl noch eine falsche vorstellung von der funktionsweise
Ein mutex ist ein Wächter der darauf auspasst , dass nur ein thread auf die Variable zugreift?
Was macht dieser Ausdruck? Warten das sich die Variable m_appState ändert?
pthread_cond_wait(¬_playing_cond, &m_appState_mutex);
muss die funktion die die variable m_appState änderet (um zu stoppen) auch ein extra thread sein?
void PlayerGB::stop() { if(m_appState == PlayerGB::PLAY) { m_appState = PlayerGB::STOP; } }
-
Du solltest vielleicht dir erstmal die Thread Grundlagen aneignen. Ansonsten solltest du mal dein Gesamtkonzept erklären.
Im Grunde läuft das meistens so: Du hast einen GUI Thread, der auch oft der Thread ist, in dem vom System main() aufgerufen wurde. Im GUI Thread läuft die GUI Event Loop. Wenn der Benutzer irgendwelche Aktionen auslöst, verändert der GUI Thread variablen oder schickt messages an die anderen Threads. Die anderen Threads erledigen die Arbeit und überprüfen ab und zu ob sich etwas geändert hat, oder warten direkt bis ein bestimmtes Event kommt.
pthread_cond_wait wartet bis eine Benachrichtigung kommt, dass sich die Condition eventuell verändert hat. Der GUI Thread kann dies mit pthread_cond_broadcast() machen. Zum Beispiel so:
void PlayerGB::stop() { pthread_mutex_lock(&m_appState_mutex); if(m_appState == PlayerGB::PLAY) { m_appState = PlayerGB::STOP; } pthread_cond_broadcast(¬_playing_cond); pthread_mutex_unlock(&m_appState_mutex); }
-
Dieser Thread wurde von Moderator/in Marc++us aus dem Forum C++ in das Forum Linux/Unix verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
hi ponto,
thx again für die antwort...es lag an einem ganz einfachen prob
ich hatte den aufruf des threads nicht mitgepostet, da ich nicht dachte das es daran liegt, aber das tat es ....ich habe statt nurpthread_create(&m_playThread, NULL, PlayerGB::play, NULL);
zu schreiben so wie es eigentlich richtig wäre
pthread_create(&m_playThread, NULL, PlayerGB::play, NULL); pthread_join(m_playThread, NULL);
geschrieben
das programm ist also nicht nach dem starten des thread zum aufrufenden thread zurückgegangen sondern ist durch join dort in der schleife hängen geblieben
hier die schleife des play_thread:
pthread_mutex_lock(&m_appState_mutex); m_appState = PlayerGB::PLAY; while(m_appState == PlayerGB::PLAY) { pthread_cond_wait(¬_playing_cond, &m_appState_mutex); } pthread_mutex_unlock(&m_appState_mutex);
hier die funktion stop_funktion
void PlayerGB::stop() { pthread_mutex_lock(&m_appState_mutex); if(m_appState == PlayerGB::PLAY) { m_appState = PlayerGB::STOP; } pthread_cond_broadcast(¬_playing_cond); pthread_mutex_unlock(&m_appState_mutex); return; }
Das Konzept sieht so aus, dass ich einen Thread zum abspielen der Songs habe ...dieser setzt ein Flag, dass er spielt ...das tut er solange wie er in der schleife ist und auf anweisung wartet...die stop funktion setzt lediglich das Flag auf STOP ...dadurch wird die schleife verlassen, das Playback wird beendet.
grüße