diff --git a/src/qprojectM-pulseaudio/PulseDeviceChooserDialog.ui b/src/qprojectM-pulseaudio/PulseDeviceChooserDialog.ui
index 60250adb5..c2f34143d 100644
--- a/src/qprojectM-pulseaudio/PulseDeviceChooserDialog.ui
+++ b/src/qprojectM-pulseaudio/PulseDeviceChooserDialog.ui
@@ -6,7 +6,7 @@
0
0
378
- 280
+ 243
@@ -32,7 +32,7 @@
20
- 250
+ 210
251
24
@@ -57,22 +57,6 @@
Select a source device below.
-
-
-
- 20
- 210
- 111
- 29
-
-
-
- Clicking on this means when projectM starts up, it will try to select the active source device to get its sound data.
-
-
- Set as default
-
-
@@ -89,30 +73,9 @@
true
-
-
- test
-
-
-
- buttonBox
- accepted()
- pulseDeviceChooserDialog
- accept()
-
-
- 248
- 254
-
-
- 157
- 274
-
-
-
buttonBox
rejected()
@@ -129,5 +92,21 @@
+
+ buttonBox
+ accepted()
+ pulseDeviceChooserDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
diff --git a/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.cpp b/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.cpp
index db1461bb4..f10b6bdb3 100644
--- a/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.cpp
+++ b/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.cpp
@@ -2,35 +2,54 @@
#include
#include
-void QPulseAudioDeviceChooser::writeSettings() {
-
- QSettings settings ( "projectM", "qprojectM-pulseaudio");
- settings.setValue ( "tryFirstAvailablePlaybackMonitor",
- this->tryFirstPlayBackMonitorCheckBox->checkState() == Qt::Checked);
-
+void QPulseAudioDeviceChooser::writeSettings()
+{
+
+ QSettings settings ( "projectM", "qprojectM-pulseaudio" );
+ settings.setValue ( "tryFirstAvailablePlaybackMonitor",
+ this->tryFirstPlayBackMonitorCheckBox->checkState() == Qt::Checked );
+
}
-void QPulseAudioDeviceChooser::readSettings() {
-
-QSettings settings ( "projectM", "qprojectM-pulseaudio");
+void QPulseAudioDeviceChooser::readSettings()
+{
+
+ QSettings settings ( "projectM", "qprojectM-pulseaudio" );
+
+ bool tryFirst = settings.value
+ ( "tryFirstAvailablePlaybackMonitor", true ).toBool() ;
+
+ this->tryFirstPlayBackMonitorCheckBox->setCheckState
+ ( tryFirst ? Qt::Checked : Qt::Unchecked );
+
+ if ( !tryFirst )
+ {
+
+
+ }
-this->tryFirstPlayBackMonitorCheckBox->setCheckState
- (settings.value("tryFirstAvailablePlaybackMonitor", true).toBool() ? Qt::Checked : Qt::Unchecked);
}
-QPulseAudioDeviceChooser::QPulseAudioDeviceChooser(const QHash & devices, QWidget * parent = 0, Qt::WindowFlags f) : QDialog(parent, f), m_qpulseAudioDeviceModel(devices, this) {
- setupUi(this);
+QPulseAudioDeviceChooser::QPulseAudioDeviceChooser ( QPulseAudioThread * qpulseAudioThread, QWidget * parent = 0, Qt::WindowFlags f ) : QDialog ( parent, f ), _qpulseAudioDeviceModel ( qpulseAudioThread->devices(), this ), _qpulseAudioThread ( qpulseAudioThread )
+{
+
+ setupUi ( this );
readSettings();
qDebug() << "setting model";
- this->devicesListView->setModel(&m_qpulseAudioDeviceModel);
+ this->devicesListView->setModel ( &_qpulseAudioDeviceModel );
+
+// void QAbstractItemView::selectionChanged ( const QItemSelection & selected, const QItemSelection & deselected ) [virtual protected slot]
+
+ connect ( devicesListView, SIGNAL ( doubleClicked ( const QModelIndex& ) ), _qpulseAudioThread, SLOT ( connectDevice ( const QModelIndex& ) ) );
+ //connect(buttonBox, SIGNAL(accepted()), _qpulseAudioThread, SLOT(connectDevice(device));
}
-void QPulseAudioDeviceChooser::open() {
-
+void QPulseAudioDeviceChooser::open()
+{
+
this->show();
- //this->devicesListView->show()
-
+
}
diff --git a/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.hpp b/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.hpp
index b0cb67daa..51cb7c3a5 100644
--- a/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.hpp
+++ b/src/qprojectM-pulseaudio/QPulseAudioDeviceChooser.hpp
@@ -2,6 +2,8 @@
#define QPULSEAUDIO_DEV_CHOOSER_HPP
#include "ui_PulseDeviceChooserDialog.h"
#include "QPulseAudioDeviceModel.hpp"
+#include "QPulseAudioThread.hpp"
+
class QDialog;
@@ -10,7 +12,7 @@ class QPulseAudioDeviceChooser : public QDialog, public Ui::pulseDeviceChooserDi
Q_OBJECT
public:
- QPulseAudioDeviceChooser(const QHash & devices, QWidget * parent, Qt::WindowFlags f=0);
+ QPulseAudioDeviceChooser(QPulseAudioThread * pulseAudioThread, QWidget * parent, Qt::WindowFlags f=0);
typedef QHash SourceContainer;
public slots:
@@ -19,6 +21,7 @@ class QPulseAudioDeviceChooser : public QDialog, public Ui::pulseDeviceChooserDi
void readSettings();
void writeSettings();
private:
- QPulseAudioDeviceModel m_qpulseAudioDeviceModel;
+ QPulseAudioDeviceModel _qpulseAudioDeviceModel;
+ QPulseAudioThread * _qpulseAudioThread;
};
#endif
diff --git a/src/qprojectM-pulseaudio/QPulseAudioThread.cpp b/src/qprojectM-pulseaudio/QPulseAudioThread.cpp
index 6720080c1..7e3e48c8a 100644
--- a/src/qprojectM-pulseaudio/QPulseAudioThread.cpp
+++ b/src/qprojectM-pulseaudio/QPulseAudioThread.cpp
@@ -74,7 +74,8 @@ static pa_sample_spec sample_spec ;
QPulseAudioThread::SourceContainer QPulseAudioThread::sourceList;
-QPulseAudioThread::QPulseAudioThread ( int _argc, char **_argv, projectM * _projectM, QObject * parent ) : QThread ( parent ), argc ( _argc ), argv ( _argv ), m_projectM ( _projectM ), sourceIndex ( -1 ) {
+QPulseAudioThread::QPulseAudioThread ( int _argc, char **_argv, projectM * _projectM, QObject * parent ) : QThread ( parent ), argc ( _argc ), argv ( _argv ), m_projectM ( _projectM ), _deviceIndex ( -1 )
+{
}
@@ -87,7 +88,9 @@ QPulseAudioThread::~QPulseAudioThread()
void QPulseAudioThread::cleanup()
{
+ _deviceIndex = -1;
pa_threaded_mainloop_stop ( mainloop );
+
if ( stream )
pa_stream_unref ( stream );
@@ -136,38 +139,14 @@ void QPulseAudioThread::cleanup()
return ;
}
-void QPulseAudioThread::connectSource ( int index )
+void QPulseAudioThread::connectHelper ( int index )
{
- if ( stream )
- pa_stream_disconnect ( stream );
-
+ assert(stream);
pa_stream_flags_t flags = ( pa_stream_flags_t ) 0;
- if ( index < 0 )
- {
- if ( sourceList.empty() )
- {
- qDebug() << "failed to discover any source devices";
- return;
- }
-
- index = -1;
- for ( SourceContainer::const_iterator pos = sourceList.begin(); pos != sourceList.end(); ++pos )
- {
- index++;
- qDebug() << "Scanning " << *pos;
- if ( ( *pos).contains ( "monitor" ) )
- {
- qDebug() << "connecting to monitor device" << *pos;
- break;
- }
- }
- assert ( !sourceList.empty() );
- }
-
- assert (index < sourceList.count());
int r;
+
if ( ( ( r = pa_stream_connect_record ( stream, sourceList[index].toStdString().c_str(), NULL, flags ) ) ) < 0 )
{
fprintf ( stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror ( pa_context_errno ( context ) ) );
@@ -175,6 +154,71 @@ void QPulseAudioThread::connectSource ( int index )
}
+int QPulseAudioThread::scanForPlaybackMonitor() {
+
+ int count = -1;
+ for ( SourceContainer::const_iterator pos = sourceList.begin(); pos != sourceList.end(); ++pos )
+ {
+ count++;
+ qDebug() << "Scanning " << *pos;
+ if ( ( *pos ).contains ( "monitor" ) )
+ {
+ return count;
+ }
+ }
+
+ /// @bug return value sucks. think
+ return 0;
+
+}
+
+void QPulseAudioThread::connectDevice ( const QModelIndex & index )
+{
+
+ if (index.isValid())
+ _deviceIndex = index.row();
+ else
+ _deviceIndex = scanForPlaybackMonitor();
+
+ qDebug() << "connect device: " << _deviceIndex;
+
+ if (stream && (pa_stream_get_state(stream) == PA_STREAM_READY))
+ {
+ //qDebug() << "disconnect";
+ pa_stream_disconnect ( stream );
+ // pa_stream_unref(stream);
+ //qDebug() << "* return *";
+
+ }
+
+ assert(context);
+
+switch (pa_stream_get_state(stream)) {
+ case PA_STREAM_UNCONNECTED:// The stream is not yet connected to any sink or source.
+ qDebug() << "unconnected: connecting...";
+ connectHelper(_deviceIndex);
+ break;
+case PA_STREAM_CREATING ://The stream is being created.
+ break;
+case PA_STREAM_READY :// The stream is established, you may pass audio data to it now.
+ connectHelper(_deviceIndex);
+
+ qDebug() << "stream is still ready, waiting for callback...";
+ break;
+case PA_STREAM_FAILED :// An error occured that made the stream invalid.
+ qDebug() << "stream is now invalid. great.";
+ break;
+case PA_STREAM_TERMINATED:// The stream has been terminated cleanly.
+ qDebug() << "terminated...";
+ break;
+}
+
+
+
+
+}
+
+
/* A shortcut for terminating the application */
void QPulseAudioThread::pulseQuit ( int ret )
{
@@ -222,38 +266,50 @@ void QPulseAudioThread::stream_read_callback ( pa_stream *s, size_t length, void
void QPulseAudioThread::stream_state_callback ( pa_stream *s, void *userdata )
{
assert ( s );
+ QPulseAudioThread * thread = (QPulseAudioThread *)userdata;
switch ( pa_stream_get_state ( s ) )
{
- case PA_STREAM_CREATING:
- case PA_STREAM_TERMINATED:
+ case PA_STREAM_UNCONNECTED:
+ qDebug() << "UNCONNECTED";
+ break;
+ case PA_STREAM_CREATING:
+ qDebug() << "CREATED";
+ break;
+ case PA_STREAM_TERMINATED:
+ qDebug() << "TERMINATED";
break;
-
case PA_STREAM_READY:
+ qDebug() << "READY";
if ( verbose )
{
const pa_buffer_attr *a;
-
fprintf ( stderr, "Stream successfully created.\n" );
if ( ! ( a = pa_stream_get_buffer_attr ( s ) ) )
fprintf ( stderr, "pa_stream_get_buffer_attr() failed: %s\n", pa_strerror ( pa_context_errno ( pa_stream_get_context ( s ) ) ) );
else
{
-
- //fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize);
+ fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize);
}
- }
-
+ }
break;
-
case PA_STREAM_FAILED:
+ qDebug() << "FAILED";
default:
fprintf ( stderr, "Stream error: %s\n", pa_strerror ( pa_context_errno ( pa_stream_get_context ( s ) ) ) );
pulseQuit ( 1 );
}
}
+
+static void stream_moved_callback(pa_stream *s, void *userdata) {
+ assert(s);
+
+ if (verbose)
+ fprintf(stderr, "Stream moved to device %s (%u, %ssuspended).\n", pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : "not ");
+}
+
/* This is called whenever the context status changes */
void QPulseAudioThread::context_state_callback ( pa_context *c, void *userdata )
{
@@ -270,12 +326,12 @@ void QPulseAudioThread::context_state_callback ( pa_context *c, void *userdata )
{
int r;
- initialize_callbacks ( ( QPulseAudioThread * ) userdata );
-
+
assert ( c && !stream );
if ( verbose )
fprintf ( stderr, "Connection established.\n" );
+
if ( ! ( stream = pa_stream_new ( c, stream_name, &sample_spec, channel_map_set ? &channel_map : NULL ) ) )
{
@@ -283,9 +339,11 @@ void QPulseAudioThread::context_state_callback ( pa_context *c, void *userdata )
goto fail;
}
- pa_stream_set_state_callback ( stream, stream_state_callback, NULL );
- pa_stream_set_read_callback ( stream, stream_read_callback, NULL );
+ initialize_callbacks ( ( QPulseAudioThread * ) userdata );
+ pa_stream_set_state_callback ( stream, stream_state_callback, userdata );
+ pa_stream_set_read_callback ( stream, stream_read_callback, userdata );
+ pa_stream_set_moved_callback(stream, stream_moved_callback, userdata);
break;
}
@@ -312,33 +370,6 @@ void QPulseAudioThread::context_drain_complete ( pa_context*c, void *userdata )
pa_context_disconnect ( c );
}
-/* Stream draining complete */
-void QPulseAudioThread::stream_drain_complete ( pa_stream*s, int success, void *userdata )
-{
- pa_operation *o;
-
- if ( !success )
- {
- fprintf ( stderr, "Failed to drain stream: %s\n", pa_strerror ( pa_context_errno ( context ) ) );
- pulseQuit ( 1 );
- }
-
- if ( verbose )
- fprintf ( stderr, "Playback stream drained.\n" );
-
- pa_stream_disconnect ( stream );
- pa_stream_unref ( stream );
- stream = NULL;
-
- if ( ! ( o = pa_context_drain ( context, context_drain_complete, NULL ) ) )
- pa_context_disconnect ( context );
- else
- {
- if ( verbose )
- fprintf ( stderr, "Draining connection to server.\n" );
- }
-}
-
/* Some data may be written to STDOUT */
void QPulseAudioThread::stdout_callback ( pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata )
{
@@ -352,9 +383,13 @@ void QPulseAudioThread::stdout_callback ( pa_mainloop_api*a, pa_io_event *e, int
}
else
{
-
projectM * prjm = static_cast ( userdata );
- prjm->pcm->addPCMfloat ( buffer+buffer_index, buffer_length/ ( sizeof ( float ) ) );
+ //int * int_buf = (int *) buffer;
+ //qDebug() << int_buf[buffer_index];
+ //qDebug() << buffer[buffer_index];
+
+ prjm->pcm->addPCMfloat
+ ( buffer+buffer_index, buffer_length / ( sizeof ( float ) ) );
assert ( buffer_length );
pa_xfree ( buffer );
@@ -414,13 +449,14 @@ void QPulseAudioThread::pa_source_info_callback ( pa_context *c, const pa_source
int index = i->index;
QString name = i->name;
- pulseThread->insertSource(index,name);
+ pulseThread->insertSource ( index,name );
}
- else {
+ else
+ {
qDebug() << "End of device list";
assert ( eol );
- pulseThread->connectSource ( -1 );
+ pulseThread->connectDevice ();
}
}
@@ -529,11 +565,11 @@ void QPulseAudioThread::run()
mainloop_api = pa_threaded_mainloop_get_api ( mainloop );
-
r = pa_signal_init ( mainloop_api );
assert ( r == 0 );
pa_signal_new ( SIGINT, exit_signal_callback, NULL );
pa_signal_new ( SIGTERM, exit_signal_callback, NULL );
+
#ifdef SIGUSR1
pa_signal_new ( SIGUSR1, sigusr1_signal_callback, NULL );
#endif
@@ -541,7 +577,6 @@ void QPulseAudioThread::run()
signal ( SIGPIPE, SIG_IGN );
#endif
-
if ( ! ( stdio_event = mainloop_api->io_new ( mainloop_api,
STDOUT_FILENO,
PA_IO_EVENT_OUTPUT,
@@ -602,6 +637,8 @@ void QPulseAudioThread::initialize_callbacks ( QPulseAudioThread * pulseThread )
//pa_operation_unref(pa_context_get_source_output_info_list(&c, source_output_info_callback, this));
//pa_operation_unref(pa_context_get_sample_info_list(&c, sample_info_callback, this));
+
+ //pa_context_set_drain
pa_context_set_subscribe_callback ( context, subscribe_callback, pulseThread );
if ( op = pa_context_subscribe ( context, ( enum pa_subscription_mask )
diff --git a/src/qprojectM-pulseaudio/QPulseAudioThread.hpp b/src/qprojectM-pulseaudio/QPulseAudioThread.hpp
index 7bddeb699..2358a09c0 100644
--- a/src/qprojectM-pulseaudio/QPulseAudioThread.hpp
+++ b/src/qprojectM-pulseaudio/QPulseAudioThread.hpp
@@ -1,9 +1,10 @@
-#ifndef PULSE_AUDIO_THREAD
+#ifndef QPULSE_AUDIO_THREAD
+#define QPULSE_AUDIO_THREAD
#include
#include
#include
#include
-
+#include
#include
extern "C"
@@ -24,7 +25,7 @@ class QPulseAudioThread : public QThread
typedef QHash SourceContainer;
QPulseAudioThread () {}
QPulseAudioThread(int _argc, char **_argv, projectM * projectM, QObject *parent);
- virtual ~QPulseAudioThread() ;
+ virtual ~QPulseAudioThread();
void run();
void cleanup();
@@ -32,13 +33,20 @@ class QPulseAudioThread : public QThread
return sourceList;
}
+ inline int deviceIndex() {
+ return _deviceIndex;
+ }
+
public slots:
inline void insertSource(int index, const QString & name) {
sourceList[index]= name;
}
- void connectSource(int index);
+ void connectDevice(const QModelIndex & index = QModelIndex());
+
private:
+ static int scanForPlaybackMonitor();
+ static void connectHelper(int index);
static void pulseQuit ( int ret );
static void stream_read_callback ( pa_stream *s, size_t length, void *userdata );
static void stream_state_callback ( pa_stream *s, void *userdata );
@@ -56,7 +64,7 @@ class QPulseAudioThread : public QThread
static SourceContainer sourceList;
- int sourceIndex;
+ int _deviceIndex;
int argc;
char ** argv;
projectM * m_projectM;
diff --git a/src/qprojectM-pulseaudio/qprojectM-pulseaudio.cpp b/src/qprojectM-pulseaudio/qprojectM-pulseaudio.cpp
index 09947292d..7c41e95b8 100644
--- a/src/qprojectM-pulseaudio/qprojectM-pulseaudio.cpp
+++ b/src/qprojectM-pulseaudio/qprojectM-pulseaudio.cpp
@@ -105,7 +105,7 @@ int main ( int argc, char*argv[] )
QPulseAudioThread * pulseThread = new QPulseAudioThread(argc, argv, mainWindow->getQProjectM(), mainWindow);
- QPulseAudioDeviceChooser devChooser(pulseThread->devices(), mainWindow);
+ QPulseAudioDeviceChooser devChooser(pulseThread, mainWindow);
QApplication::connect(&pulseAction, SIGNAL(triggered()), &devChooser, SLOT(open()));
pulseThread->start();