hacking way to correct behavior in device chooser

git-svn-id: https://projectm.svn.sourceforge.net/svnroot/projectm/trunk@754 6778bc44-b910-0410-a7a0-be141de4315d
This commit is contained in:
w1z7ard
2008-01-21 03:08:04 +00:00
parent c2ecb34ce2
commit 58858ae83b
6 changed files with 186 additions and 140 deletions

View File

@ -6,7 +6,7 @@
<x>0</x>
<y>0</y>
<width>378</width>
<height>280</height>
<height>243</height>
</rect>
</property>
<property name="windowTitle" >
@ -32,7 +32,7 @@
<property name="geometry" >
<rect>
<x>20</x>
<y>250</y>
<y>210</y>
<width>251</width>
<height>24</height>
</rect>
@ -57,22 +57,6 @@
<string>Select a source device below.</string>
</property>
</widget>
<widget class="QPushButton" name="saveAsDefaultPushButton" >
<property name="geometry" >
<rect>
<x>20</x>
<y>210</y>
<width>111</width>
<height>29</height>
</rect>
</property>
<property name="toolTip" >
<string>Clicking on this means when projectM starts up, it will try to select the active source device to get its sound data.</string>
</property>
<property name="text" >
<string>Set as default</string>
</property>
</widget>
<widget class="QListView" name="devicesListView" >
<property name="geometry" >
<rect>
@ -89,30 +73,9 @@
<bool>true</bool>
</property>
</widget>
<action name="actionTest" >
<property name="text" >
<string>test</string>
</property>
</action>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>pulseDeviceChooserDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
@ -129,5 +92,21 @@
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>pulseDeviceChooserDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -2,35 +2,54 @@
#include <QSettings>
#include <QtDebug>
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<int, QString> & 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()
}

View File

@ -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<int, QString> & devices, QWidget * parent, Qt::WindowFlags f=0);
QPulseAudioDeviceChooser(QPulseAudioThread * pulseAudioThread, QWidget * parent, Qt::WindowFlags f=0);
typedef QHash<int, QString> 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

View File

@ -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<projectM *> ( 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 )

View File

@ -1,9 +1,10 @@
#ifndef PULSE_AUDIO_THREAD
#ifndef QPULSE_AUDIO_THREAD
#define QPULSE_AUDIO_THREAD
#include <QObject>
#include <QTimer>
#include <QThread>
#include <QString>
#include <QModelIndex>
#include <QHash>
extern "C"
@ -24,7 +25,7 @@ class QPulseAudioThread : public QThread
typedef QHash<int, QString> 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;

View File

@ -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();