Merge pull request #4196 from arnova/sub_fallback
[vuplus_xbmc] / xbmc / cores / AudioEngine / Sinks / AESinkPULSE.cpp
1 /*
2  *      Copyright (C) 2010-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20 #include "system.h"
21 #ifdef HAS_PULSEAUDIO
22 #include "AESinkPULSE.h"
23 #include "utils/log.h"
24 #include "Util.h"
25 #include "guilib/LocalizeStrings.h"
26
27 using namespace std;
28
29 static const char *ContextStateToString(pa_context_state s)
30 {
31   switch (s)
32   {
33     case PA_CONTEXT_UNCONNECTED:
34       return "unconnected";
35     case PA_CONTEXT_CONNECTING:
36       return "connecting";
37     case PA_CONTEXT_AUTHORIZING:
38       return "authorizing";
39     case PA_CONTEXT_SETTING_NAME:
40       return "setting name";
41     case PA_CONTEXT_READY:
42       return "ready";
43     case PA_CONTEXT_FAILED:
44       return "failed";
45     case PA_CONTEXT_TERMINATED:
46       return "terminated";
47     default:
48       return "none";
49   }
50 }
51
52 static const char *StreamStateToString(pa_stream_state s)
53 {
54   switch(s)
55   {
56     case PA_STREAM_UNCONNECTED:
57       return "unconnected";
58     case PA_STREAM_CREATING:
59       return "creating";
60     case PA_STREAM_READY:
61       return "ready";
62     case PA_STREAM_FAILED:
63       return "failed";
64     case PA_STREAM_TERMINATED:
65       return "terminated";
66     default:
67       return "none";
68   }
69 }
70
71 static pa_sample_format AEFormatToPulseFormat(AEDataFormat format)
72 {
73   switch (format)
74   {
75     case AE_FMT_U8    : return PA_SAMPLE_U8;
76     case AE_FMT_S16LE : return PA_SAMPLE_S16LE;
77     case AE_FMT_S16BE : return PA_SAMPLE_S16BE;
78     case AE_FMT_S16NE : return PA_SAMPLE_S16NE;
79     case AE_FMT_S24LE3: return PA_SAMPLE_S24LE;
80     case AE_FMT_S24BE3: return PA_SAMPLE_S24BE;
81     case AE_FMT_S24NE3: return PA_SAMPLE_S24NE;
82     case AE_FMT_S24LE4: return PA_SAMPLE_S24_32LE;
83     case AE_FMT_S24BE4: return PA_SAMPLE_S24_32BE;
84     case AE_FMT_S24NE4: return PA_SAMPLE_S24_32NE;
85     case AE_FMT_S32BE : return PA_SAMPLE_S32BE;
86     case AE_FMT_S32LE : return PA_SAMPLE_S32LE;
87     case AE_FMT_S32NE : return PA_SAMPLE_S32NE;
88     case AE_FMT_FLOAT : return PA_SAMPLE_FLOAT32;
89
90     case AE_FMT_AC3:
91     case AE_FMT_DTS:
92     case AE_FMT_EAC3:
93       return PA_SAMPLE_S16NE;
94
95     default:
96       return PA_SAMPLE_INVALID;
97   }
98 }
99
100 static pa_encoding AEFormatToPulseEncoding(AEDataFormat format)
101 {
102   switch (format)
103   {
104     case AE_FMT_AC3   : return PA_ENCODING_AC3_IEC61937;
105     case AE_FMT_DTS   : return PA_ENCODING_DTS_IEC61937;
106     case AE_FMT_EAC3  : return PA_ENCODING_EAC3_IEC61937;
107
108     default:
109       return PA_ENCODING_PCM;
110   }
111 }
112
113 static AEDataFormat defaultDataFormats[] = {
114   AE_FMT_U8,
115   AE_FMT_S16LE,
116   AE_FMT_S16BE,
117   AE_FMT_S16NE,
118   AE_FMT_S24LE3,
119   AE_FMT_S24BE3,
120   AE_FMT_S24NE3,
121   AE_FMT_S24LE4,
122   AE_FMT_S24BE4,
123   AE_FMT_S24NE4,
124   AE_FMT_S32BE,
125   AE_FMT_S32LE,
126   AE_FMT_S32NE,
127   AE_FMT_FLOAT
128 };
129
130 static unsigned int defaultSampleRates[] = {
131   5512,
132   8000,
133   11025,
134   16000,
135   22050,
136   32000,
137   44100,
138   48000,
139   64000,
140   88200,
141   96000,
142   176400,
143   192000,
144   384000
145 };
146
147 /* Static callback functions */
148
149 static void ContextStateCallback(pa_context *c, void *userdata)
150 {
151   pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata;
152   switch (pa_context_get_state(c))
153   {
154     case PA_CONTEXT_READY:
155     case PA_CONTEXT_TERMINATED:
156     case PA_CONTEXT_UNCONNECTED:
157     case PA_CONTEXT_CONNECTING:
158     case PA_CONTEXT_AUTHORIZING:
159     case PA_CONTEXT_SETTING_NAME:
160     case PA_CONTEXT_FAILED:
161       pa_threaded_mainloop_signal(m, 0);
162       break;
163   }
164 }
165
166 static void StreamStateCallback(pa_stream *s, void *userdata)
167 {
168   pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata;
169   switch (pa_stream_get_state(s))
170   {
171     case PA_STREAM_UNCONNECTED:
172     case PA_STREAM_CREATING:
173     case PA_STREAM_READY:
174     case PA_STREAM_FAILED:
175     case PA_STREAM_TERMINATED:
176       pa_threaded_mainloop_signal(m, 0);
177       break;
178   }
179 }
180
181 static void StreamRequestCallback(pa_stream *s, size_t length, void *userdata)
182 {
183   pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata;
184   pa_threaded_mainloop_signal(m, 0);
185 }
186
187 static void StreamLatencyUpdateCallback(pa_stream *s, void *userdata)
188 {
189   pa_threaded_mainloop *m = (pa_threaded_mainloop *)userdata;
190   pa_threaded_mainloop_signal(m, 0);
191 }
192
193 static void SinkChangedCallback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata)
194 {
195   CAESinkPULSE* p = (CAESinkPULSE*) userdata;
196   if(!p)
197     return;
198
199   CSingleLock lock(p->m_sec);
200   if (p->IsInitialized())
201   {
202     if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW)
203     {
204        CLog::Log(LOGDEBUG, "Sink appeared");
205        CAEFactory::DeviceChange();
206     }
207     else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE)
208     {
209       CLog::Log(LOGDEBUG, "Sink removed");
210       CAEFactory::DeviceChange();
211     }
212     else if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_CHANGE)
213     {
214       CLog::Log(LOGDEBUG, "Sink changed");
215       //CAEFactory::DeviceChange();
216     }    
217   }
218 }
219
220 struct SinkInfoStruct
221 {
222   AEDeviceInfoList *list;
223   bool isHWDevice;
224   bool device_found;
225   pa_threaded_mainloop *mainloop;
226   SinkInfoStruct()
227   {
228     list = NULL;
229     isHWDevice = false;
230     device_found = true;
231     mainloop = NULL;
232   }
233 };
234
235 static void SinkInfoCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
236 {
237   SinkInfoStruct *sinkStruct = (SinkInfoStruct *)userdata;
238   if(i)
239   {
240     if (i->flags && (i->flags & PA_SINK_HARDWARE))
241       sinkStruct->isHWDevice = true;
242
243     sinkStruct->device_found = true;
244   }
245   pa_threaded_mainloop_signal(sinkStruct->mainloop, 0);
246 }
247
248 static AEChannel PAChannelToAEChannel(pa_channel_position_t channel)
249 {
250   AEChannel ae_channel;
251   switch (channel)
252   {
253     case PA_CHANNEL_POSITION_FRONT_LEFT:            ae_channel = AE_CH_FL; break;
254     case PA_CHANNEL_POSITION_FRONT_RIGHT:           ae_channel = AE_CH_FR; break;
255     case PA_CHANNEL_POSITION_FRONT_CENTER:          ae_channel = AE_CH_FC; break;
256     case PA_CHANNEL_POSITION_LFE:                   ae_channel = AE_CH_LFE; break;
257     case PA_CHANNEL_POSITION_REAR_LEFT:             ae_channel = AE_CH_BL; break;
258     case PA_CHANNEL_POSITION_REAR_RIGHT:            ae_channel = AE_CH_BR; break;
259     case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:  ae_channel = AE_CH_FLOC; break;
260     case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: ae_channel = AE_CH_FROC; break;
261     case PA_CHANNEL_POSITION_REAR_CENTER:           ae_channel = AE_CH_BC; break;
262     case PA_CHANNEL_POSITION_SIDE_LEFT:             ae_channel = AE_CH_SL; break;
263     case PA_CHANNEL_POSITION_SIDE_RIGHT:            ae_channel = AE_CH_SR; break;
264     case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:        ae_channel = AE_CH_TFL; break;
265     case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:       ae_channel = AE_CH_TFR; break;
266     case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:      ae_channel = AE_CH_TFC; break;
267     case PA_CHANNEL_POSITION_TOP_CENTER:            ae_channel = AE_CH_TC; break;
268     case PA_CHANNEL_POSITION_TOP_REAR_LEFT:         ae_channel = AE_CH_TBL; break;
269     case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:        ae_channel = AE_CH_TBR; break;
270     case PA_CHANNEL_POSITION_TOP_REAR_CENTER:       ae_channel = AE_CH_TBC; break;
271     default:                                        ae_channel = AE_CH_NULL; break;
272   }
273   return ae_channel;
274 }
275
276 static pa_channel_position_t AEChannelToPAChannel(AEChannel ae_channel)
277 {
278   pa_channel_position_t pa_channel;
279   switch (ae_channel)
280   {
281     case AE_CH_FL:    pa_channel = PA_CHANNEL_POSITION_FRONT_LEFT; break;
282     case AE_CH_FR:    pa_channel = PA_CHANNEL_POSITION_FRONT_RIGHT; break;
283     case AE_CH_FC:    pa_channel = PA_CHANNEL_POSITION_FRONT_CENTER; break;
284     case AE_CH_LFE:   pa_channel = PA_CHANNEL_POSITION_LFE; break;
285     case AE_CH_BL:    pa_channel = PA_CHANNEL_POSITION_REAR_LEFT; break;
286     case AE_CH_BR:    pa_channel = PA_CHANNEL_POSITION_REAR_RIGHT; break;
287     case AE_CH_FLOC:  pa_channel = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER; break;
288     case AE_CH_FROC:  pa_channel = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER; break;
289     case AE_CH_BC:    pa_channel = PA_CHANNEL_POSITION_REAR_CENTER; break;
290     case AE_CH_SL:    pa_channel = PA_CHANNEL_POSITION_SIDE_LEFT; break;
291     case AE_CH_SR:    pa_channel = PA_CHANNEL_POSITION_SIDE_RIGHT; break;
292     case AE_CH_TFL:   pa_channel = PA_CHANNEL_POSITION_TOP_FRONT_LEFT; break;
293     case AE_CH_TFR:   pa_channel = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT; break;
294     case AE_CH_TFC:   pa_channel = PA_CHANNEL_POSITION_TOP_FRONT_CENTER; break;
295     case AE_CH_TC:    pa_channel = PA_CHANNEL_POSITION_TOP_CENTER; break;
296     case AE_CH_TBL:   pa_channel = PA_CHANNEL_POSITION_TOP_REAR_LEFT; break;
297     case AE_CH_TBR:   pa_channel = PA_CHANNEL_POSITION_TOP_REAR_RIGHT; break;
298     case AE_CH_TBC:   pa_channel = PA_CHANNEL_POSITION_TOP_REAR_CENTER; break;
299     default:          pa_channel = PA_CHANNEL_POSITION_INVALID; break;
300   }
301   return pa_channel;
302 }
303
304 static pa_channel_map AEChannelMapToPAChannel(CAEChannelInfo info)
305 {
306   pa_channel_map map;
307   pa_channel_map_init(&map);
308   pa_channel_position_t pos;
309   for (unsigned int i = 0; i < info.Count(); ++i)
310   {
311     pos = AEChannelToPAChannel(info[i]);
312     if(pos != PA_CHANNEL_POSITION_INVALID)
313     {
314       // remember channel name and increase channel count
315       map.map[map.channels++] = pos;
316     }
317   }
318   return map;
319 }
320
321 static CAEChannelInfo PAChannelToAEChannelMap(pa_channel_map channels)
322 {
323   CAEChannelInfo info;
324   AEChannel ch;
325   info.Reset();
326   for (unsigned int i=0; i<channels.channels; i++)
327   {
328     ch = PAChannelToAEChannel(channels.map[i]);
329     if(ch != AE_CH_NULL)
330       info += ch;
331   }
332   return info;
333 }
334
335 static void SinkInfoRequestCallback(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
336 {
337
338   SinkInfoStruct *sinkStruct = (SinkInfoStruct *)userdata;
339
340   if(sinkStruct && sinkStruct->list->empty())
341   {
342     //add a default device first
343     CAEDeviceInfo defaultDevice;
344     defaultDevice.m_deviceName = std::string("Default");
345     defaultDevice.m_displayName = std::string("Default");
346     defaultDevice.m_displayNameExtra = std::string("Default Output Device (PULSEAUDIO)");
347     defaultDevice.m_dataFormats.insert(defaultDevice.m_dataFormats.end(), defaultDataFormats, defaultDataFormats + sizeof(defaultDataFormats) / sizeof(defaultDataFormats[0]));
348     defaultDevice.m_channels = CAEChannelInfo(AE_CH_LAYOUT_2_0);
349     defaultDevice.m_sampleRates.assign(defaultSampleRates, defaultSampleRates + sizeof(defaultSampleRates) / sizeof(defaultSampleRates[0]));
350     defaultDevice.m_deviceType = AE_DEVTYPE_PCM;
351     sinkStruct->list->push_back(defaultDevice);
352   }
353   bool valid = true;
354   if (i && i->name)
355   {
356     CAEDeviceInfo device;
357
358     device.m_deviceName = string(i->name);
359     device.m_displayName = string(i->description);
360     if (i->active_port && i->active_port->description)
361       device.m_displayNameExtra = std::string((i->active_port->description)).append(" (PULSEAUDIO)");
362     else
363       device.m_displayNameExtra = std::string((i->description)).append(" (PULSEAUDIO)");
364     unsigned int device_type = AE_DEVTYPE_PCM; //0
365
366     device.m_channels = PAChannelToAEChannelMap(i->channel_map);
367
368     // Don't add devices that would not have a channel map
369     if(device.m_channels.Count() == 0)
370       valid = false;
371
372     device.m_sampleRates.assign(defaultSampleRates, defaultSampleRates + sizeof(defaultSampleRates) / sizeof(defaultSampleRates[0]));
373
374     for (unsigned int j = 0; j < i->n_formats; j++)
375     {
376       switch(i->formats[j]->encoding)
377       {
378         case PA_ENCODING_AC3_IEC61937:
379           device.m_dataFormats.push_back(AE_FMT_AC3);
380           device_type = AE_DEVTYPE_IEC958;
381           break;
382         case PA_ENCODING_DTS_IEC61937:
383           device.m_dataFormats.push_back(AE_FMT_DTS);
384           device_type = AE_DEVTYPE_IEC958;
385           break;
386         case PA_ENCODING_EAC3_IEC61937:
387           device.m_dataFormats.push_back(AE_FMT_EAC3);
388           device_type = AE_DEVTYPE_IEC958;
389           break;
390         case PA_ENCODING_PCM:
391           device.m_dataFormats.insert(device.m_dataFormats.end(), defaultDataFormats, defaultDataFormats + sizeof(defaultDataFormats) / sizeof(defaultDataFormats[0]));
392           break;
393         default:
394           break;
395       }
396     }
397     // passthrough is only working when device has Stereo channel config
398     if (device_type > AE_DEVTYPE_PCM && device.m_channels.Count() == 2)
399       device.m_deviceType = AE_DEVTYPE_IEC958;
400     else
401       device.m_deviceType = AE_DEVTYPE_PCM;
402     if(valid)
403     {
404       CLog::Log(LOGDEBUG, "PulseAudio: Found %s with devicestring %s", device.m_displayName.c_str(), device.m_deviceName.c_str());
405       sinkStruct->list->push_back(device);
406     }
407     else
408     {
409       CLog::Log(LOGDEBUG, "PulseAudio: Skipped %s with devicestring %s", device.m_displayName.c_str(), device.m_deviceName.c_str());
410     }
411  }
412   pa_threaded_mainloop_signal(sinkStruct->mainloop, 0);
413 }
414
415 /* PulseAudio class memberfunctions*/
416
417
418 CAESinkPULSE::CAESinkPULSE()
419 {
420   m_IsAllocated = false;
421   m_passthrough = false;
422   m_MainLoop = NULL;
423   m_BytesPerSecond = 0;
424   m_BufferSize = 0;
425   m_Channels = 0;
426   m_Stream = NULL;
427   m_Context = NULL;
428 }
429
430 CAESinkPULSE::~CAESinkPULSE()
431 {
432   Deinitialize();
433 }
434
435 bool CAESinkPULSE::Initialize(AEAudioFormat &format, std::string &device)
436 {
437   {
438     CSingleLock lock(m_sec);
439     m_IsAllocated = false;
440   }
441   m_passthrough = false;
442   m_BytesPerSecond = 0;
443   m_BufferSize = 0;
444   m_Channels = 0;
445   m_Stream = NULL;
446   m_Context = NULL;
447
448   if (!SetupContext(NULL, &m_Context, &m_MainLoop))
449   {
450     CLog::Log(LOGNOTICE, "PulseAudio might not be running. Context was not created.");
451     Deinitialize();
452     return false;
453   }
454
455   pa_threaded_mainloop_lock(m_MainLoop);
456
457   {
458     // Register Callback for Sink changes
459     CSingleLock lock(m_sec);
460     pa_context_set_subscribe_callback(m_Context, SinkChangedCallback, this);
461     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK;
462     pa_operation *op = pa_context_subscribe(m_Context, mask, NULL, this);
463     if (op != NULL)
464       pa_operation_unref(op);
465   }
466
467   struct pa_channel_map map;
468   pa_channel_map_init(&map);
469
470   m_passthrough = AE_IS_RAW(format.m_dataFormat);
471
472   if(m_passthrough)
473   {
474     map.channels = 2;
475     format.m_channelLayout = AE_CH_LAYOUT_2_0;
476   }
477   else
478   {
479     map = AEChannelMapToPAChannel(format.m_channelLayout);
480     // if count has changed we need to fit the AE Map
481     if(map.channels != format.m_channelLayout.Count())
482       format.m_channelLayout = PAChannelToAEChannelMap(map);
483   }
484   m_Channels = format.m_channelLayout.Count();
485
486   pa_cvolume_reset(&m_Volume, m_Channels);
487
488   pa_format_info *info[1];
489   info[0] = pa_format_info_new();
490   info[0]->encoding = AEFormatToPulseEncoding(format.m_dataFormat);
491   if(!m_passthrough)
492   {
493     pa_format_info_set_sample_format(info[0], AEFormatToPulseFormat(format.m_dataFormat));
494     pa_format_info_set_channel_map(info[0], &map);
495   }
496   pa_format_info_set_channels(info[0], m_Channels);
497
498   // PA requires m_encodedRate in order to do EAC3
499   unsigned int samplerate;
500   if (m_passthrough)
501   {
502     if (format.m_encodedRate == 0)
503     {
504       CLog::Log(LOGNOTICE, "PulseAudio: Passthrough in use but m_encodedRate is not set - fallback to m_sampleRate");
505       samplerate = format.m_sampleRate;
506     }
507     else
508       samplerate = format.m_encodedRate;
509   }
510   else
511     samplerate = format.m_sampleRate;
512
513   pa_format_info_set_rate(info[0], samplerate);
514
515   if (!pa_format_info_valid(info[0]))
516   {
517     CLog::Log(LOGERROR, "PulseAudio: Invalid format info");
518     pa_format_info_free(info[0]);
519     pa_threaded_mainloop_unlock(m_MainLoop);
520     Deinitialize();
521     return false;
522   }
523
524   pa_sample_spec spec;
525   #if PA_CHECK_VERSION(2,0,0)
526     pa_format_info_to_sample_spec(info[0], &spec, NULL);
527   #else
528     spec.rate = (AEFormatToPulseEncoding(format.m_dataFormat) == PA_ENCODING_EAC3_IEC61937) ? 4 * samplerate : samplerate;
529     spec.format = AEFormatToPulseFormat(format.m_dataFormat);
530     spec.channels = m_Channels;
531   #endif
532   if (!pa_sample_spec_valid(&spec))
533   {
534     CLog::Log(LOGERROR, "PulseAudio: Invalid sample spec");
535     pa_format_info_free(info[0]);
536     pa_threaded_mainloop_unlock(m_MainLoop);
537     Deinitialize();
538     return false;
539   }
540
541   m_BytesPerSecond = pa_bytes_per_second(&spec);
542   unsigned int frameSize = pa_frame_size(&spec);
543
544   m_Stream = pa_stream_new_extended(m_Context, "audio stream", info, 1, NULL);
545   pa_format_info_free(info[0]);
546
547   if (m_Stream == NULL)
548   {
549     CLog::Log(LOGERROR, "PulseAudio: Could not create a stream");
550     pa_threaded_mainloop_unlock(m_MainLoop);
551     Deinitialize();
552     return false;
553   }
554
555   pa_stream_set_state_callback(m_Stream, StreamStateCallback, m_MainLoop);
556   pa_stream_set_write_callback(m_Stream, StreamRequestCallback, m_MainLoop);
557   pa_stream_set_latency_update_callback(m_Stream, StreamLatencyUpdateCallback, m_MainLoop);
558
559   bool isDefaultDevice = (device == "Default");
560
561   pa_buffer_attr buffer_attr;
562   SinkInfoStruct sinkStruct;
563   sinkStruct.mainloop = m_MainLoop;
564   sinkStruct.isHWDevice = false;
565   sinkStruct.device_found = true; // needed to get default device opened
566
567   if (!isDefaultDevice)
568   {
569     // we need to check if the device we want to open really exists
570     // default device is handled in a special manner
571     sinkStruct.device_found = false; // if sink is valid it will be set true in pa_context_get_sink_info_by_name
572     WaitForOperation(pa_context_get_sink_info_by_name(m_Context, device.c_str(),SinkInfoCallback, &sinkStruct), m_MainLoop, "Get Sink Info");
573   }
574
575   if(!sinkStruct.device_found) // ActiveAE will open us again with a valid device name
576   {
577     CLog::Log(LOGERROR, "PulseAudio: Sink %s not found", device.c_str());
578     pa_threaded_mainloop_unlock(m_MainLoop);
579     Deinitialize();
580     return false;
581   }
582
583   // 200ms max latency
584   // 50ms min packet size
585   if(sinkStruct.isHWDevice || isDefaultDevice)
586   {
587     unsigned int latency = m_BytesPerSecond / 5;
588     unsigned int process_time = latency / 4;
589     memset(&buffer_attr, 0, sizeof(buffer_attr));
590     buffer_attr.tlength = (uint32_t) latency;
591     buffer_attr.minreq = (uint32_t) process_time;
592     buffer_attr.maxlength = (uint32_t) -1;
593     buffer_attr.prebuf = (uint32_t) -1;
594     buffer_attr.fragsize = (uint32_t) latency;
595   }
596
597   if (pa_stream_connect_playback(m_Stream, isDefaultDevice ? NULL : device.c_str(), sinkStruct.isHWDevice ? &buffer_attr : NULL, ((pa_stream_flags)(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_ADJUST_LATENCY)), m_passthrough ? NULL : &m_Volume, NULL) < 0)
598   {
599     CLog::Log(LOGERROR, "PulseAudio: Failed to connect stream to output");
600     pa_threaded_mainloop_unlock(m_MainLoop);
601     Deinitialize();
602     return false;
603   }
604
605   /* Wait until the stream is ready */
606   do
607   {
608     pa_threaded_mainloop_wait(m_MainLoop);
609     CLog::Log(LOGDEBUG, "PulseAudio: Stream %s", StreamStateToString(pa_stream_get_state(m_Stream)));
610   }
611   while (pa_stream_get_state(m_Stream) != PA_STREAM_READY && pa_stream_get_state(m_Stream) != PA_STREAM_FAILED);
612
613   if (pa_stream_get_state(m_Stream) == PA_STREAM_FAILED)
614   {
615     CLog::Log(LOGERROR, "PulseAudio: Waited for the stream but it failed");
616     pa_threaded_mainloop_unlock(m_MainLoop);
617     Deinitialize();
618     return false;
619   }
620
621   const pa_buffer_attr *a;
622
623   if (!(a = pa_stream_get_buffer_attr(m_Stream)))
624   {
625     CLog::Log(LOGERROR, "PulseAudio: %s", pa_strerror(pa_context_errno(m_Context)));
626     pa_threaded_mainloop_unlock(m_MainLoop);
627     Deinitialize();
628     return false;
629   }
630   else
631   {
632     unsigned int packetSize = a->minreq;
633     m_BufferSize = a->tlength;
634
635     format.m_frames = packetSize / frameSize;
636   }
637
638   pa_threaded_mainloop_unlock(m_MainLoop);
639   
640   format.m_frameSize = frameSize;
641   format.m_frameSamples = format.m_frames * format.m_channelLayout.Count();
642   m_format = format;
643   format.m_dataFormat = m_passthrough ? AE_FMT_S16NE : format.m_dataFormat;
644
645   Pause(false);
646   {
647     CSingleLock lock(m_sec);
648     m_IsAllocated = true;
649   }
650
651   return true;
652 }
653
654 void CAESinkPULSE::Deinitialize()
655 {
656   CSingleLock lock(m_sec);
657   m_IsAllocated = false;
658   m_passthrough = false;
659
660   if (m_Stream)
661     Drain();
662
663   if (m_MainLoop)
664     pa_threaded_mainloop_stop(m_MainLoop);
665
666   if (m_Stream)
667   {
668     pa_stream_disconnect(m_Stream);
669     pa_stream_unref(m_Stream);
670     m_Stream = NULL;
671   }
672
673   if (m_Context)
674   {
675     pa_context_disconnect(m_Context);
676     pa_context_unref(m_Context);
677     m_Context = NULL;
678   }
679
680   if (m_MainLoop)
681   {
682     pa_threaded_mainloop_free(m_MainLoop);
683     m_MainLoop = NULL;
684   }
685 }
686
687 double CAESinkPULSE::GetDelay()
688 {
689   if (!m_IsAllocated)
690     return 0;
691
692   int error = 0;
693   pa_usec_t latency = (pa_usec_t) -1;
694   pa_threaded_mainloop_lock(m_MainLoop);
695   if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
696   {
697     if (error == -PA_ERR_NODATA)
698     {
699       WaitForOperation(pa_stream_update_timing_info(m_Stream, NULL,NULL), m_MainLoop, "Update Timing Information");
700       if ((error = pa_stream_get_latency(m_Stream, &latency, NULL)) < 0)
701       {
702         CLog::Log(LOGDEBUG, "GetDelay - Failed to get Latency %d", error); 
703       }
704     }
705   }
706   if (error < 0 )
707     latency = (pa_usec_t) 0;
708
709   pa_threaded_mainloop_unlock(m_MainLoop);
710   return latency / 1000000.0;
711 }
712
713 double CAESinkPULSE::GetCacheTotal()
714 {
715   return (float)m_BufferSize / (float)m_BytesPerSecond;
716 }
717
718 unsigned int CAESinkPULSE::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
719 {
720   if (!m_IsAllocated)
721     return frames;
722
723   pa_threaded_mainloop_lock(m_MainLoop);
724
725   unsigned int available = frames * m_format.m_frameSize;
726   unsigned int length = 0;
727   // revisit me after Gotham - should use a callback for the write function
728   while ((length = pa_stream_writable_size(m_Stream)) == 0)
729     pa_threaded_mainloop_wait(m_MainLoop);
730
731   length =  std::min((unsigned int)length, available);
732
733   int error = pa_stream_write(m_Stream, data, length, NULL, 0, PA_SEEK_RELATIVE);
734   pa_threaded_mainloop_unlock(m_MainLoop);
735
736   if (error)
737   {
738     CLog::Log(LOGERROR, "CPulseAudioDirectSound::AddPackets - pa_stream_write failed\n");
739     return 0;
740   }
741
742   return (unsigned int)(length / m_format.m_frameSize);
743 }
744
745 void CAESinkPULSE::Drain()
746 {
747   if (!m_IsAllocated)
748     return;
749
750   pa_threaded_mainloop_lock(m_MainLoop);
751   WaitForOperation(pa_stream_drain(m_Stream, NULL, NULL), m_MainLoop, "Drain");
752   pa_threaded_mainloop_unlock(m_MainLoop);
753 }
754
755 void CAESinkPULSE::SetVolume(float volume)
756 {
757   if (m_IsAllocated && !m_passthrough)
758   {
759     pa_threaded_mainloop_lock(m_MainLoop);
760     pa_volume_t pavolume = pa_sw_volume_from_linear(volume);
761     if ( pavolume <= 0 )
762       pa_cvolume_mute(&m_Volume, m_Channels);
763     else
764       pa_cvolume_set(&m_Volume, m_Channels, pavolume);
765     pa_operation *op = pa_context_set_sink_input_volume(m_Context, pa_stream_get_index(m_Stream), &m_Volume, NULL, NULL);
766     if (op == NULL)
767       CLog::Log(LOGERROR, "PulseAudio: Failed to set volume");
768     else
769       pa_operation_unref(op);
770
771     pa_threaded_mainloop_unlock(m_MainLoop);
772   }
773 }
774
775 void CAESinkPULSE::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
776 {
777   pa_context *context;
778   pa_threaded_mainloop *mainloop;
779
780   if (!SetupContext(NULL, &context, &mainloop))
781   {
782     CLog::Log(LOGNOTICE, "PulseAudio might not be running. Context was not created.");
783     return;
784   }
785
786   pa_threaded_mainloop_lock(mainloop);
787
788   SinkInfoStruct sinkStruct;
789   sinkStruct.mainloop = mainloop;
790   sinkStruct.list = &list;
791   WaitForOperation(pa_context_get_sink_info_list(context, SinkInfoRequestCallback, &sinkStruct), mainloop, "EnumerateAudioSinks");
792
793   pa_threaded_mainloop_unlock(mainloop);
794
795   if (mainloop)
796     pa_threaded_mainloop_stop(mainloop);
797
798   if (context)
799   {
800     pa_context_disconnect(context);
801     pa_context_unref(context);
802     context = NULL;
803   }
804
805   if (mainloop)
806   {
807     pa_threaded_mainloop_free(mainloop);
808     mainloop = NULL;
809   }
810 }
811
812 bool CAESinkPULSE::IsInitialized()
813 {
814  CSingleLock lock(m_sec);
815  return m_IsAllocated; 
816 }
817
818 bool CAESinkPULSE::Pause(bool pause)
819 {
820   pa_threaded_mainloop_lock(m_MainLoop);
821
822   if (!WaitForOperation(pa_stream_cork(m_Stream, pause ? 1 : 0, NULL, NULL), m_MainLoop, pause ? "Pause" : "Resume"))
823     pause = !pause;
824
825   pa_threaded_mainloop_unlock(m_MainLoop);
826
827   return pause;
828 }
829
830 inline bool CAESinkPULSE::WaitForOperation(pa_operation *op, pa_threaded_mainloop *mainloop, const char *LogEntry = "")
831 {
832   if (op == NULL)
833     return false;
834
835   bool sucess = true;
836
837   while (pa_operation_get_state(op) == PA_OPERATION_RUNNING)
838     pa_threaded_mainloop_wait(mainloop);
839
840   if (pa_operation_get_state(op) != PA_OPERATION_DONE)
841   {
842     CLog::Log(LOGERROR, "PulseAudio: %s Operation failed", LogEntry);
843     sucess = false;
844   }
845
846   pa_operation_unref(op);
847   return sucess;
848 }
849
850 bool CAESinkPULSE::SetupContext(const char *host, pa_context **context, pa_threaded_mainloop **mainloop)
851 {
852   if ((*mainloop = pa_threaded_mainloop_new()) == NULL)
853   {
854     CLog::Log(LOGERROR, "PulseAudio: Failed to allocate main loop");
855     return false;
856   }
857
858   if (((*context) = pa_context_new(pa_threaded_mainloop_get_api(*mainloop), "XBMC")) == NULL)
859   {
860     CLog::Log(LOGERROR, "PulseAudio: Failed to allocate context");
861     return false;
862   }
863
864   pa_context_set_state_callback(*context, ContextStateCallback, *mainloop);
865
866   if (pa_context_connect(*context, host, (pa_context_flags_t)0, NULL) < 0)
867   {
868     CLog::Log(LOGERROR, "PulseAudio: Failed to connect context");
869     return false;
870   }
871   pa_threaded_mainloop_lock(*mainloop);
872
873   if (pa_threaded_mainloop_start(*mainloop) < 0)
874   {
875     CLog::Log(LOGERROR, "PulseAudio: Failed to start MainLoop");
876     pa_threaded_mainloop_unlock(*mainloop);
877     return false;
878   }
879
880   /* Wait until the context is ready */
881   do
882   {
883     pa_threaded_mainloop_wait(*mainloop);
884     CLog::Log(LOGDEBUG, "PulseAudio: Context %s", ContextStateToString(pa_context_get_state(*context)));
885   }
886   while (pa_context_get_state(*context) != PA_CONTEXT_READY && pa_context_get_state(*context) != PA_CONTEXT_FAILED);
887
888   if (pa_context_get_state(*context) == PA_CONTEXT_FAILED)
889   {
890     CLog::Log(LOGERROR, "PulseAudio: Waited for the Context but it failed");
891     pa_threaded_mainloop_unlock(*mainloop);
892     return false;
893   }
894
895   pa_threaded_mainloop_unlock(*mainloop);
896   return true;
897 }
898 #endif