2
* This file is part of the qx11grab project
4
* Copyright (C) Juergen Heinemann (Undefined) http://qx11grab.hjcms.de, (C) 2007-2012
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public License
17
* along with this library; see the file COPYING.LIB. If not, write to
18
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19
* Boston, MA 02110-1301, USA.
22
#include "pulseaudiodialog.h"
25
#include <QtCore/QCoreApplication>
26
#include <QtCore/QByteArray>
27
#include <QtCore/QDebug>
28
#include <QtCore/QGlobalStatic>
29
#include <QtCore/QList>
30
#include <QtCore/QVariant>
33
#include <QtDBus/QDBusConnection>
34
#include <QtDBus/QDBusInterface>
37
#include <QtGui/QListWidgetItem>
41
#include <pulse/context.h>
42
#include <pulse/mainloop.h>
43
#include <pulse/introspect.h>
44
#include <pulse/error.h>
47
static pa_mainloop_api* mainloop_api = NULL;
48
static pa_context* context = NULL;
51
* send errors to mainWindow
53
static void sendPulseErrorToMainWindow ( const char* error )
55
QString message ( "Pulse:" );
56
message.append ( QString::fromUtf8 ( error ) );
58
QDBusInterface iface ( "de.hjcms.qx11grab", "/", "de.hjcms.qx11grab" );
59
iface.call ( "message", message );
63
* struct for simple list of Card Input Sources
64
* \note struct for pa_source_info
66
typedef struct PaDevInfo
74
/** Insert all input cards into pulseInfo */
75
static QList<PaDevInfo> pulseInfo;
77
/** Pulse "pa_context_get_source_info_list" callback function */
78
static void getPulseSourceInfo ( pa_context *co, const pa_source_info *i, int success, void * state )
82
if ( pa_context_errno ( co ) == PA_ERR_NOENTITY )
85
mainloop_api->quit ( mainloop_api, 0 );
95
const char* key = pa_proplist_iterate ( i->proplist, &state );
98
if ( QString::fromUtf8 ( key ).contains ( "device.class", Qt::CaseInsensitive ) )
100
inp = !QString::fromUtf8 ( pa_proplist_gets ( i->proplist, key ) ).contains ( "monitor", Qt::CaseInsensitive );
103
key = pa_proplist_iterate ( i->proplist, &state );
107
// qDebug() << "Pulse::getPulseSourceInfo >> " << i->index << i->name << i->description << inp;
109
devinfo.index = i->index;
110
devinfo.name = QString ( i->name );
111
devinfo.description = QString ( i->description );
112
devinfo.isInputDevice = inp;
113
pulseInfo.append ( devinfo );
116
/** Pulse "pa_context_set_state_callback" callback function */
117
static void pulseContextState ( pa_context *c, void *userdata )
119
padevinfo_t* dummy = static_cast<padevinfo_t*> ( userdata );
123
switch ( pa_context_get_state ( c ) )
125
case PA_CONTEXT_CONNECTING:
126
case PA_CONTEXT_AUTHORIZING:
127
case PA_CONTEXT_SETTING_NAME:
130
case PA_CONTEXT_READY:
132
qDebug ( "QX11Grab: connection established." );
134
if ( ! ( o = pa_context_get_source_info_list ( c, getPulseSourceInfo, dummy ) ) )
136
const char* errorMessage = pa_strerror ( pa_context_errno ( c ) );
137
fprintf ( stderr, "QX11Grab: pulse context get card info list failed! - %s\n", errorMessage );
138
sendPulseErrorToMainWindow ( errorMessage );
139
mainloop_api->quit ( mainloop_api, 0 );
142
pa_operation_unref ( o );
146
case PA_CONTEXT_TERMINATED:
147
mainloop_api->quit ( mainloop_api, 0 );
150
case PA_CONTEXT_FAILED:
153
const char* errorMessage = pa_strerror ( pa_context_errno ( c ) );
154
fprintf ( stderr, "QX11Grab: context error - %s\n", errorMessage );
155
sendPulseErrorToMainWindow ( errorMessage );
156
mainloop_api->quit ( mainloop_api, 0 );
162
/** \class PulseAudioDialog */
163
PulseAudioDialog::PulseAudioDialog ( QWidget * parent )
164
: AbstractAudioDialog ( parent )
166
setObjectName ( QLatin1String ( "PulseAudioDialog" ) );
168
setWindowTitle ( trUtf8 ( "Pulse Device Selection" ) );
169
m_deviceListWidget->clear();
175
* Füge Inhalte in \b DeviceListWidget
177
void PulseAudioDialog::insertItems()
179
int size = pulseInfo.size();
180
QIcon inputIcon = QIcon::fromTheme ( "audio-input-microphone" );
181
QIcon monitorIcon = QIcon::fromTheme ( "audio-card" );
184
for ( int i = 0; i < size; ++i )
186
QString index = QString::number ( pulseInfo.at ( i ).index );
187
QString name = pulseInfo.at ( i ).name;
188
QString desc = pulseInfo.at ( i ).description;
189
QListWidgetItem* item = new QListWidgetItem ( m_deviceListWidget );
190
item->setText ( desc );
191
item->setData ( Qt::UserRole, name );
192
item->setData ( Qt::ToolTipRole, QString ( "%1 = %2" ).arg ( index, name ) );
193
item->setData ( Qt::StatusTipRole, desc );
194
if ( pulseInfo.at ( i ).isInputDevice )
195
item->setData ( Qt::DecorationRole, inputIcon );
197
item->setData ( Qt::DecorationRole, monitorIcon );
199
m_deviceListWidget->addItem ( item );
205
* main method to get interfaces from pulseaudio server
206
* http://freedesktop.org/software/pulseaudio/doxygen/async.html
208
void PulseAudioDialog::initInterface()
210
pa_mainloop* mloop = NULL;
212
QByteArray client_name ( "qx11grab" );
215
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_mainloop_new";
216
mloop = pa_mainloop_new();
219
fprintf ( stderr, "QX11Grab: Set up a new pulse main loop failed with.\n" );
223
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_mainloop_get_api";
224
mainloop_api = pa_mainloop_get_api ( mloop );
226
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_context_new";
227
context = pa_context_new ( mainloop_api, client_name.constData() );
230
fprintf ( stderr, "QX11Grab: Create a new pulse connection context failed.\n" );
231
pa_mainloop_free ( mloop );
235
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_context_set_state_callback";
236
pa_context_set_state_callback ( context, pulseContextState, NULL );
238
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_context_connect";
239
if ( pa_context_connect ( context, server, PA_CONTEXT_NOFLAGS, NULL ) < 0 )
241
fprintf ( stderr, "QX11Grab: Pulse connection failed.\n" );
242
pa_mainloop_free ( mloop );
246
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_mainloop_run";
247
if ( pa_mainloop_run ( mloop, &ret ) < 0 )
249
fprintf ( stderr, "QX11Grab: Running pulse mainloop failed.\n" );
250
pa_mainloop_free ( mloop );
254
// qDebug() << Q_FUNC_INFO << __LINE__ << "pa_mainloop_free";
255
qDebug ( "QX11Grab: pulse source info done." );
256
pa_context_unref ( context );
257
pa_mainloop_free ( mloop );
262
PulseAudioDialog::~PulseAudioDialog()