Create one QThread per one C thread
authorJuho Vähä-Herttua <juhovh@iki.fi>
Sat, 19 May 2012 09:16:43 +0000 (12:16 +0300)
committerJuho Vähä-Herttua <juhovh@iki.fi>
Sat, 19 May 2012 10:10:31 +0000 (13:10 +0300)
AirTV-Qt/AirTV.pro
AirTV-Qt/audiocallbacks.h
src/bindings/qt4/raopcallbacks.h
src/bindings/qt4/raopservice.cpp
src/bindings/qt4/raopservice.h

index ef524ab4d939b60dd76cc1f5bc7feed4e1ec93c4..8c896c55df5bc3731a91f9ddf212a14b1a6c4e8e 100644 (file)
@@ -81,3 +81,7 @@ RESOURCES += \
 
 
 
+
+
+
+
index 835dd46766e39ef197af4793368e77c2b9b8848f..52b30b0e39b78f50daf1e31c3d4999cad18dc8d4 100644 (file)
@@ -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);
index 53a44684a1e4245efa3d2b31aec79189e71222f7..07fd7ed24c1d40ab56e05b370a0e9d23b705b0de 100644 (file)
@@ -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;
 
index f575aa20969c3e1dce41cbaebb6cdcbf5dfd8502..2656ad26af20fa05b598640a6cbb3d8d9cc11977 100644 (file)
@@ -1,5 +1,7 @@
 #include "raopservice.h"
+#include "raopcallbackhandler.h"
 
+#include <QThread>
 #include <QDebug>
 
 #include <shairplay/raop.h>
 "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();
-    }
 }
index d01b7343bf0a2eaa2d6286a681cbbae299a18871..6531e03bfd5b0ac7634a8abb0142bc23c19cca09 100644 (file)
@@ -2,9 +2,8 @@
 #define RAOPSERVICE_H
 
 #include <QObject>
-#include <QThread>
 
-#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: