From f65165f4a61e4ecab5cd6159c01723d5115352b4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Juho=20V=C3=A4h=C3=A4-Herttua?= Date: Sat, 19 May 2012 12:16:43 +0300 Subject: [PATCH] Create one QThread per one C thread --- AirTV-Qt/AirTV.pro | 4 ++ AirTV-Qt/audiocallbacks.h | 2 +- src/bindings/qt4/raopcallbacks.h | 2 +- src/bindings/qt4/raopservice.cpp | 94 ++++++++++++++++++++++---------- src/bindings/qt4/raopservice.h | 6 +- 5 files changed, 71 insertions(+), 37 deletions(-) diff --git a/AirTV-Qt/AirTV.pro b/AirTV-Qt/AirTV.pro index ef524ab..8c896c5 100644 --- a/AirTV-Qt/AirTV.pro +++ b/AirTV-Qt/AirTV.pro @@ -81,3 +81,7 @@ RESOURCES += \ + + + + diff --git a/AirTV-Qt/audiocallbacks.h b/AirTV-Qt/audiocallbacks.h index 835dd46..52b30b0 100644 --- a/AirTV-Qt/audiocallbacks.h +++ b/AirTV-Qt/audiocallbacks.h @@ -11,7 +11,7 @@ class AudioCallbacks : public RaopCallbacks public: explicit AudioCallbacks(QObject *parent = 0); - virtual void * audioInit(int bits, int channels, int samplerate); + virtual void *audioInit(int bits, int channels, int samplerate); virtual void audioSetVolume(void *session, float volume); virtual void audioProcess(void *session, const QByteArray &buffer); virtual void audioFlush(void *session); diff --git a/src/bindings/qt4/raopcallbacks.h b/src/bindings/qt4/raopcallbacks.h index 53a4468..07fd7ed 100644 --- a/src/bindings/qt4/raopcallbacks.h +++ b/src/bindings/qt4/raopcallbacks.h @@ -9,7 +9,7 @@ class RaopCallbacks : public QObject public: explicit RaopCallbacks(QObject *parent = 0) : QObject(parent) {} - virtual void * audioInit(int bits, int channels, int samplerate) = 0; + virtual void *audioInit(int bits, int channels, int samplerate) = 0; virtual void audioProcess(void *session, const QByteArray & buffer) = 0; virtual void audioDestroy(void *session) = 0; diff --git a/src/bindings/qt4/raopservice.cpp b/src/bindings/qt4/raopservice.cpp index f575aa2..2656ad2 100644 --- a/src/bindings/qt4/raopservice.cpp +++ b/src/bindings/qt4/raopservice.cpp @@ -1,5 +1,7 @@ #include "raopservice.h" +#include "raopcallbackhandler.h" +#include #include #include @@ -29,24 +31,45 @@ "2gG0N5hvJpzwwhbhXqFKA4zaaSrw622wDniAK5MlIE0tIAKKP4yxNGjoD2QYjhBGuhvkWKY=\n"\ "-----END RSA PRIVATE KEY-----\n" +typedef struct { + QThread * cb_thread; + RaopCallbackHandler * cb_handler; + void * cb_session; +} audio_session_t; static void* audio_init_cb(void *cls, int bits, int channels, int samplerate) { - void *session; - QMetaObject::invokeMethod((QObject*)cls, "audioInit", Qt::BlockingQueuedConnection, - Q_ARG(void*, (void*)&session), + audio_session_t *audio_session = 0; + + audio_session = (audio_session_t *)calloc(1, sizeof(audio_session_t)); + audio_session->cb_thread = new QThread(); + audio_session->cb_thread->start(); + + /* This whole hack is required because QAudioOutput + * needs to be created in a QThread, threads created + * outside Qt are not allowed (they have no eventloop) */ + audio_session->cb_handler = new RaopCallbackHandler(); + audio_session->cb_handler->moveToThread(audio_session->cb_thread); + audio_session->cb_handler->init((RaopCallbacks *)cls); + + QMetaObject::invokeMethod(audio_session->cb_handler, "audioInit", + Qt::BlockingQueuedConnection, + Q_ARG(void*, (void*)&audio_session->cb_session), Q_ARG(int, bits), Q_ARG(int, channels), Q_ARG(int, samplerate)); - return session; + return audio_session; } static void audio_process_cb(void *cls, void *session, const void *buffer, int buflen) { - QMetaObject::invokeMethod((QObject*)cls, "audioProcess", Qt::BlockingQueuedConnection, - Q_ARG(void*, session), + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioProcess", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session), Q_ARG(void*, (void*)buffer), Q_ARG(int, buflen)); } @@ -54,30 +77,51 @@ audio_process_cb(void *cls, void *session, const void *buffer, int buflen) static void audio_destroy_cb(void *cls, void *session) { - QMetaObject::invokeMethod((QObject*)cls, "audioDestroy", Qt::BlockingQueuedConnection, - Q_ARG(void*, session)); + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioDestroy", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session)); + + // Wait until the session thread has finished + audio_session->cb_thread->quit(); + audio_session->cb_thread->wait(); + + // Delete all session variables + delete audio_session->cb_handler; + delete audio_session->cb_thread; + free(audio_session); } static void audio_flush_cb(void *cls, void *session) { - QMetaObject::invokeMethod((QObject*)cls, "audioFlush", Qt::BlockingQueuedConnection, - Q_ARG(void*, session)); + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioFlush", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session)); } static void audio_set_volume_cb(void *cls, void *session, float volume) { - QMetaObject::invokeMethod((QObject*)cls, "audioSetVolume", Qt::BlockingQueuedConnection, - Q_ARG(void*, session), + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioSetVolume", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session), Q_ARG(float, volume)); } static void audio_set_metadata_cb(void *cls, void *session, const void *buffer, int buflen) { - QMetaObject::invokeMethod((QObject*)cls, "audioSetVolume", Qt::BlockingQueuedConnection, - Q_ARG(void*, session), + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioSetVolume", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session), Q_ARG(void*, (void*)buffer), Q_ARG(int, buflen)); } @@ -85,8 +129,11 @@ audio_set_metadata_cb(void *cls, void *session, const void *buffer, int buflen) static void audio_set_coverart_cb(void *cls, void *session, const void *buffer, int buflen) { - QMetaObject::invokeMethod((QObject*)cls, "audioSetVolume", Qt::BlockingQueuedConnection, - Q_ARG(void*, session), + Q_UNUSED(cls) + audio_session_t *audio_session = (audio_session_t *)session; + QMetaObject::invokeMethod(audio_session->cb_handler, "audioSetVolume", + Qt::BlockingQueuedConnection, + Q_ARG(void*, audio_session->cb_session), Q_ARG(void*, (void*)buffer), Q_ARG(int, buflen)); } @@ -95,10 +142,6 @@ RaopService::RaopService(QObject *parent) : QObject(parent), m_raop(0) { - /* This whole hack is required because QAudioOutput - * needs to be created in a QThread, threads created - * outside Qt are not allowed (they have no eventloop) */ - m_handler.moveToThread(&m_thread); } RaopService::~RaopService() @@ -111,8 +154,7 @@ bool RaopService::init(int max_clients, RaopCallbacks *callbacks) { raop_callbacks_t raop_cbs; - m_handler.init(callbacks); - raop_cbs.cls = &m_handler; + raop_cbs.cls = callbacks; raop_cbs.audio_init = &audio_init_cb; raop_cbs.audio_process = &audio_process_cb; raop_cbs.audio_destroy = &audio_destroy_cb; @@ -123,7 +165,6 @@ bool RaopService::init(int max_clients, RaopCallbacks *callbacks) m_raop = raop_init(max_clients, &raop_cbs, RSA_KEY); if (!m_raop) { - printf("Foobar\n"); return false; } return true; @@ -137,11 +178,8 @@ bool RaopService::isRunning() bool RaopService::start(quint16 port, const QByteArray & hwaddr) { int ret; - m_thread.start(); ret = raop_start(m_raop, &port, hwaddr.data(), hwaddr.size(), 0); if (ret < 0) { - m_thread.quit(); - m_thread.wait(); return false; } return true; @@ -152,8 +190,4 @@ void RaopService::stop() if (m_raop) { raop_stop(m_raop); } - if (m_thread.isRunning()) { - m_thread.quit(); - m_thread.wait(); - } } diff --git a/src/bindings/qt4/raopservice.h b/src/bindings/qt4/raopservice.h index d01b734..6531e03 100644 --- a/src/bindings/qt4/raopservice.h +++ b/src/bindings/qt4/raopservice.h @@ -2,9 +2,8 @@ #define RAOPSERVICE_H #include -#include -#include "raopcallbackhandler.h" +#include "raopcallbacks.h" #include "raop.h" @@ -23,9 +22,6 @@ public: private: raop_t * m_raop; - QThread m_thread; - RaopCallbackHandler m_handler; - signals: public slots: -- 2.34.1