2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "CAudioIODef.h"
23 using namespace tizen_media_audio;
27 * class CPulseAudioClient
29 const char* CPulseAudioClient::CLIENT_NAME = "AUDIO_IO_PA_CLIENT";
31 CPulseAudioClient::CPulseAudioClient(EStreamDirection direction,
32 CPulseStreamSpec& spec,
33 IPulseStreamListener* listener)
34 : mDirection(direction), mSpec(spec), mpListener(listener),
35 mpMainloop(NULL), mpContext(NULL), mpStream(NULL),
36 mpPropList(NULL), mIsInit(false), mIsOperationSuccess(false) {
39 CPulseAudioClient::~CPulseAudioClient() {
43 void CPulseAudioClient::_contextStateChangeCb(pa_context* c, void* user_data) {
44 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
48 switch (pa_context_get_state(c)) {
49 case PA_CONTEXT_READY:
50 AUDIO_IO_LOGD("The context is ready!");
51 case PA_CONTEXT_FAILED:
52 case PA_CONTEXT_TERMINATED:
53 pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
56 case PA_CONTEXT_UNCONNECTED:
57 case PA_CONTEXT_CONNECTING:
58 case PA_CONTEXT_AUTHORIZING:
59 case PA_CONTEXT_SETTING_NAME:
64 void CPulseAudioClient::_successContextCb(pa_context* c, int success, void* user_data) {
65 AUDIO_IO_LOGD("pa_context[%p], success[%d], user_data[%p]", c, success, user_data);
69 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
70 pClient->mIsOperationSuccess = static_cast<bool>(success);
72 pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
75 void CPulseAudioClient::_streamStateChangeCb(pa_stream* s, void* user_data) {
79 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
81 switch (pa_stream_get_state(s)) {
83 AUDIO_IO_LOGD("The stream is ready!");
84 pClient->mpListener->onStateChanged(CAudioInfo::AUDIO_IO_STATE_RUNNING);
85 case PA_STREAM_FAILED:
86 case PA_STREAM_TERMINATED:
87 pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
90 case PA_STREAM_UNCONNECTED:
92 case PA_STREAM_CREATING:
97 void CPulseAudioClient::_streamCaptureCb(pa_stream* s, size_t length, void* user_data) {
101 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
102 assert(pClient->mpListener);
104 pClient->mpListener->onStream(pClient, length);
107 void CPulseAudioClient::_streamPlaybackCb(pa_stream* s, size_t length, void* user_data) {
108 //AUDIO_IO_LOGD("_streamPlaybackCb()");
112 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
113 assert(pClient->mpListener);
115 if (pClient->mIsInit == false) {
116 AUDIO_IO_LOGD("Occurred this listener when an out stream is on the way to create - Dummy write[length:%d]", length);
118 char* dummy = new char[length];
119 memset(dummy, 0, length);
120 pa_stream_write(s, dummy, length, NULL, 0LL, PA_SEEK_RELATIVE);
126 pClient->mpListener->onStream(pClient, length);
129 void CPulseAudioClient::_streamLatencyUpdateCb(pa_stream* s, void* user_data) {
133 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
135 pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
138 void CPulseAudioClient::_successStreamCb(pa_stream* s, int success, void* user_data) {
139 AUDIO_IO_LOGD("pa_stream[%p], success[%d], user_data[%p]", s, success, user_data);
143 CPulseAudioClient* pClient = static_cast<CPulseAudioClient*>(user_data);
144 pClient->mIsOperationSuccess = static_cast<bool>(success);
146 pa_threaded_mainloop_signal(pClient->mpMainloop, 0);
149 void CPulseAudioClient::initialize() throw (CAudioError) {
151 if (mIsInit == true) {
159 // Allocates PA proplist
160 mpPropList = pa_proplist_new();
161 if (mpPropList == NULL) {
162 THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_proplist_new()");
165 // Adds values on proplist for delivery to PULSEAUDIO
166 char *streamType = NULL;
167 CAudioInfo::EAudioType audioType = mSpec.getAudioInfo().getAudioType();
168 mSpec.getAudioInfo().convertAudioType2StreamType(audioType, &streamType);
169 pa_proplist_sets(mpPropList, PA_PROP_MEDIA_ROLE, streamType);
171 int index = mSpec.getAudioInfo().getAudioIndex();
173 pa_proplist_setf(mpPropList, PA_PROP_MEDIA_PARENT_ID, "%u", (unsigned int) index);
176 // Adds latency on proplist for delivery to PULSEAUDIO
177 CPulseStreamSpec::EStreamLatency latency = mSpec.getStreamLatency();
178 AUDIO_IO_LOGD("LATENCY : %d", latency);
180 pa_proplist_setf(mpPropList, PA_PROP_MEDIA_TIZEN_AUDIO_LATENCY, "%d", latency);
182 // Allocates PA mainloop
183 mpMainloop = pa_threaded_mainloop_new();
184 if (mpMainloop == NULL) {
185 THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_threaded_mainloop_new()");
188 // Allocates PA context
189 mpContext = pa_context_new(pa_threaded_mainloop_get_api(mpMainloop), CLIENT_NAME);
190 if (mpContext == NULL) {
191 THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_context_new()");
194 // Sets context state changed callback
195 pa_context_set_state_callback(mpContext, _contextStateChangeCb, this);
197 // Connects this client with PA server
198 if (pa_context_connect(mpContext, NULL, PA_CONTEXT_NOFLAGS, NULL) < 0) {
199 THROW_ERROR_MSG(CAudioError::ERROR_OUT_OF_MEMORY, "Failed pa_context_connect()");
202 // LOCK for synchronous connection
203 pa_threaded_mainloop_lock(mpMainloop);
206 if (pa_threaded_mainloop_start(mpMainloop) < 0) {
207 pa_threaded_mainloop_unlock(mpMainloop);
208 THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_threaded_mainloop_start()");
211 // Connection process is asynchronously
212 // So, this function will be waited when occurred context state change event
213 // If I got a signal, do next processing
215 pa_context_state_t state;
216 state = pa_context_get_state(mpContext);
218 if (state == PA_CONTEXT_READY) {
222 if (!PA_CONTEXT_IS_GOOD(state)) {
223 err = pa_context_errno(mpContext);
224 pa_threaded_mainloop_unlock(mpMainloop);
225 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "pa_context's state is not good err:[%d]", err);
228 /* Wait until the context is ready */
229 pa_threaded_mainloop_wait(mpMainloop);
232 // Allocates PA stream
233 pa_sample_spec ss = mSpec.getSampleSpec();
234 pa_channel_map map = mSpec.getChannelMap();
236 mpStream = pa_stream_new_with_proplist(mpContext, mSpec.getStreamName(), &ss, &map, mpPropList);
237 if (mpStream == NULL) {
238 pa_threaded_mainloop_unlock(mpMainloop);
239 THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_new_with_proplist()()");
242 // Sets stream callbacks
243 pa_stream_set_state_callback(mpStream, _streamStateChangeCb, this);
244 pa_stream_set_read_callback(mpStream, _streamCaptureCb, this);
245 pa_stream_set_write_callback(mpStream, _streamPlaybackCb, this);
246 pa_stream_set_latency_update_callback(mpStream, _streamLatencyUpdateCb, this);
248 // Connect stream with PA Server
250 if (mDirection == STREAM_DIRECTION_PLAYBACK) {
251 pa_stream_flags_t flags = static_cast<pa_stream_flags_t>(
252 PA_STREAM_INTERPOLATE_TIMING |
253 PA_STREAM_ADJUST_LATENCY |
254 PA_STREAM_AUTO_TIMING_UPDATE);
256 ret = pa_stream_connect_playback(mpStream, NULL, NULL, flags, NULL, NULL);
258 pa_stream_flags_t flags = static_cast<pa_stream_flags_t>(
259 PA_STREAM_INTERPOLATE_TIMING |
260 PA_STREAM_ADJUST_LATENCY |
261 PA_STREAM_AUTO_TIMING_UPDATE);
263 ret = pa_stream_connect_record(mpStream, NULL, NULL, flags);
267 err = pa_context_errno(mpContext);
268 pa_threaded_mainloop_unlock(mpMainloop);
269 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_connect() err:[%d]", err);
273 pa_stream_state_t state;
274 state = pa_stream_get_state(mpStream);
276 if (state == PA_STREAM_READY) {
277 AUDIO_IO_LOGD("STREAM READY");
281 if (!PA_STREAM_IS_GOOD(state)) {
282 err = pa_context_errno(mpContext);
283 pa_threaded_mainloop_unlock(mpMainloop);
284 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INTERNAL_OPERATION, "pa_stream's state is not good err:[%d]", err);
287 /* Wait until the stream is ready */
288 pa_threaded_mainloop_wait(mpMainloop);
291 // End of synchronous
292 pa_threaded_mainloop_unlock(mpMainloop);
295 } catch (CAudioError e) {
301 void CPulseAudioClient::finalize() {
303 if (mIsInit == false) {
307 if (mpMainloop != NULL) {
308 pa_threaded_mainloop_stop(mpMainloop);
310 if (mpStream != NULL) {
311 pa_stream_disconnect(mpStream);
315 if (mpContext != NULL) {
316 pa_context_disconnect(mpContext);
317 pa_context_unref(mpContext);
321 if (mpMainloop != NULL) {
322 pa_threaded_mainloop_free(mpMainloop);
326 if (mpPropList != NULL) {
327 pa_proplist_free(mpPropList);
334 int CPulseAudioClient::peek(const void** data, size_t* length) throw (CAudioError) {
335 if (mIsInit == false) {
336 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
339 #ifdef _AUDIO_IO_DEBUG_TIMING_
340 AUDIO_IO_LOGD("data:[%p], length:[%p]", data, length);
345 if (data == NULL || length == NULL) {
346 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_INVALID_ARGUMENT, "The parameter is invalid - data:%p, length:%p", data, length);
349 if (mDirection == STREAM_DIRECTION_PLAYBACK) {
350 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
355 if (isInThread() == false) {
356 pa_threaded_mainloop_lock(mpMainloop);
357 ret = pa_stream_peek(mpStream, data, length);
358 pa_threaded_mainloop_unlock(mpMainloop);
360 ret = pa_stream_peek(mpStream, data, length);
364 THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_peek()");
370 int CPulseAudioClient::drop() throw (CAudioError) {
371 if (mIsInit == false) {
372 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
375 #ifdef _AUDIO_IO_DEBUG_TIMING_
381 if (mDirection == STREAM_DIRECTION_PLAYBACK) {
382 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
387 if (isInThread() == false) {
388 pa_threaded_mainloop_lock(mpMainloop);
389 ret = pa_stream_drop(mpStream);
390 pa_threaded_mainloop_unlock(mpMainloop);
392 ret = pa_stream_drop(mpStream);
396 THROW_ERROR_MSG(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_drop()");
402 int CPulseAudioClient::write(const void* data, size_t length) throw (CAudioError) {
403 if (mIsInit == false) {
404 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
407 #ifdef _AUDIO_IO_DEBUG_TIMING_
408 AUDIO_IO_LOGD("data[%p], length:[%d]", data, length);
413 if (data == NULL || length < 0) {
414 THROW_ERROR_MSG(CAudioError::ERROR_INVALID_ARGUMENT, "The parameter is invalid");
417 if (mDirection == STREAM_DIRECTION_RECORD) {
418 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "The Playback client couldn't use this function");
423 if (isInThread() == false) {
424 pa_threaded_mainloop_lock(mpMainloop);
425 ret = pa_stream_write(mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
426 pa_threaded_mainloop_unlock(mpMainloop);
428 ret = pa_stream_write(mpStream, data, length, NULL, 0LL, PA_SEEK_RELATIVE);
432 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_write() err:%d", ret);
438 void CPulseAudioClient::cork(bool cork) throw (CAudioError) {
439 AUDIO_IO_LOGD("bool cork:%d", cork);
441 if (mIsInit == false) {
442 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
445 if (isInThread() == true) {
446 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This operation is not supported in callback");
451 if (isInThread() == false) {
452 pa_threaded_mainloop_lock(mpMainloop);
453 pa_operation_unref(pa_stream_cork(mpStream, static_cast<int>(cork), _successStreamCb, this));
454 pa_threaded_mainloop_unlock(mpMainloop);
456 pa_operation_unref(pa_stream_cork(mpStream, static_cast<int>(cork), _successStreamCb, this));
462 bool CPulseAudioClient::isCorked() throw (CAudioError) {
463 if (mIsInit == false) {
464 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
471 if (isInThread() == false) {
472 pa_threaded_mainloop_lock(mpMainloop);
473 isCork = pa_stream_is_corked(mpStream);
474 pa_threaded_mainloop_unlock(mpMainloop);
476 isCork = pa_stream_is_corked(mpStream);
479 AUDIO_IO_LOGD("isCork:%d", isCork);
480 return static_cast<bool>(isCork);
483 bool CPulseAudioClient::drain() throw (CAudioError) {
484 AUDIO_IO_LOGD("drain");
486 if (mIsInit == false) {
487 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
492 if (isInThread() == false) {
493 pa_threaded_mainloop_lock(mpMainloop);
494 pa_operation_unref(pa_stream_drain(mpStream, _successStreamCb, this));
495 pa_threaded_mainloop_unlock(mpMainloop);
497 pa_operation_unref(pa_stream_drain(mpStream, _successStreamCb, this));
503 bool CPulseAudioClient::flush() throw (CAudioError) {
504 AUDIO_IO_LOGD("flush");
506 if (mIsInit == false) {
507 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
512 if (isInThread() == false) {
513 pa_threaded_mainloop_lock(mpMainloop);
514 pa_operation_unref(pa_stream_flush(mpStream, _successStreamCb, this));
515 pa_threaded_mainloop_unlock(mpMainloop);
517 pa_operation_unref(pa_stream_flush(mpStream, _successStreamCb, this));
523 size_t CPulseAudioClient::getWritableSize() throw (CAudioError) {
524 if (mIsInit == false) {
525 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
530 if (mDirection != STREAM_DIRECTION_PLAYBACK) {
531 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This client is used for Playback");
536 if (isInThread() == false) {
537 pa_threaded_mainloop_lock(mpMainloop);
538 ret = pa_stream_writable_size(mpStream);
539 pa_threaded_mainloop_unlock(mpMainloop);
541 ret = pa_stream_writable_size(mpStream);
547 void CPulseAudioClient::checkRunningState() throw (CAudioError) {
548 if (mIsInit == false) {
549 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
552 if (mpContext == NULL || PA_CONTEXT_IS_GOOD(pa_context_get_state(mpContext)) == 0) {
553 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The context[%p] is not created or not good state", mpContext);
555 if (mpStream == NULL || PA_STREAM_IS_GOOD(pa_stream_get_state(mpStream)) == 0) {
556 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The stream[%p] is not created or not good state", mpStream);
558 if (pa_context_get_state(mpContext) != PA_CONTEXT_READY || pa_stream_get_state(mpStream) != PA_STREAM_READY) {
559 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_INITIALIZED, "The context[%p] or stream[%p] state is not ready", mpContext, mpStream);
562 #ifdef _AUDIO_IO_DEBUG_TIMING_
563 AUDIO_IO_LOGD("This client is running");
567 bool CPulseAudioClient::isInThread() throw (CAudioError) {
568 if (mIsInit == false) {
569 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
572 int ret = pa_threaded_mainloop_in_thread(mpMainloop);
574 #ifdef _AUDIO_IO_DEBUG_TIMING_
575 AUDIO_IO_LOGD("isInThread : [%d][TRUE:1][FALSE:0]", ret);
577 return static_cast<bool>(ret);
580 size_t CPulseAudioClient::getReadableSize() throw (CAudioError) {
581 if (mIsInit == false) {
582 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
587 if (mDirection != STREAM_DIRECTION_RECORD) {
588 THROW_ERROR_MSG(CAudioError::ERROR_NOT_SUPPORTED, "This client is used for Capture");
593 if (isInThread() == false) {
594 pa_threaded_mainloop_lock(mpMainloop);
595 ret = pa_stream_writable_size(mpStream);
596 pa_threaded_mainloop_unlock(mpMainloop);
598 ret = pa_stream_writable_size(mpStream);
604 size_t CPulseAudioClient::getBufferSize() throw (CAudioError) {
605 if (mIsInit == false) {
606 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
614 if (isInThread() == false) {
615 pa_threaded_mainloop_lock(mpMainloop);
618 const pa_buffer_attr* attr = pa_stream_get_buffer_attr(mpStream);
620 int _err = pa_context_errno(mpContext);
621 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_buffer_attr() err:%d", _err);
624 if (mDirection == STREAM_DIRECTION_PLAYBACK) {
626 AUDIO_IO_LOGD("PLAYBACK buffer size : %d", ret);
628 ret = attr->fragsize;
629 AUDIO_IO_LOGD("RECORD buffer size : %d", ret);
631 } catch (CAudioError err) {
632 if (isInThread() == false) {
633 pa_threaded_mainloop_unlock(mpMainloop);
638 if (isInThread() == false) {
639 pa_threaded_mainloop_unlock(mpMainloop);
645 pa_usec_t CPulseAudioClient::getLatency() throw (CAudioError) {
646 if (mIsInit == false) {
647 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
655 if (isInThread() == false) {
656 if (pa_stream_get_latency(mpStream, &ret, &negative) < 0) {
657 int _err = pa_context_errno(mpContext);
658 if (_err != PA_ERR_NODATA) {
659 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_latency() err:%d", _err);
662 return negative ? 0 : ret;
665 pa_threaded_mainloop_lock(mpMainloop);
669 if (pa_stream_get_latency(mpStream, &ret, &negative) >= 0) {
673 int _err = pa_context_errno(mpContext);
674 if (_err != PA_ERR_NODATA) {
675 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_FAILED_OPERATION, "Failed pa_stream_get_latency() err:%d", _err);
678 /* Wait until latency data is available again */
679 pa_threaded_mainloop_wait(mpMainloop);
681 } catch (CAudioError e) {
682 pa_threaded_mainloop_unlock(mpMainloop);
686 pa_threaded_mainloop_unlock(mpMainloop);
688 return negative ? 0 : ret;
691 pa_usec_t CPulseAudioClient::getFinalLatency() throw (CAudioError) {
692 if (mIsInit == false) {
693 THROW_ERROR_MSG(CAudioError::ERROR_NOT_INITIALIZED, "Did not initialize CPulseAudioClient");
702 if (isInThread() == false) {
703 pa_threaded_mainloop_lock(mpMainloop);
706 ver = pa_context_get_server_protocol_version(mpContext);
708 const pa_buffer_attr* buffer_attr = pa_stream_get_buffer_attr(mpStream);
709 const pa_sample_spec* sample_spec = pa_stream_get_sample_spec(mpStream);
710 const pa_timing_info* timing_info = pa_stream_get_timing_info(mpStream);
712 if (buffer_attr == NULL || sample_spec == NULL || timing_info == NULL) {
713 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_OUT_OF_MEMORY, "Failed to get buffer_attr[%p] or sample_spec[%p] or timing_info[%p] from a pa_stream",
714 buffer_attr, sample_spec, timing_info);
717 if (mDirection == STREAM_DIRECTION_PLAYBACK) {
718 ret = (pa_bytes_to_usec(buffer_attr->tlength, sample_spec) + timing_info->configured_sink_usec);
719 AUDIO_IO_LOGD("FINAL PLAYBACK LATENCY : %d", ret);
721 ret = (pa_bytes_to_usec(buffer_attr->fragsize, sample_spec) + timing_info->configured_source_usec);
722 AUDIO_IO_LOGD("FINAL RECORD LATENCY : %d", ret);
725 THROW_ERROR_MSG_FORMAT(CAudioError::ERROR_NOT_SUPPORTED, "This version(ver.%d) is not supported", ver);
728 if (isInThread() == false) {
729 pa_threaded_mainloop_unlock(mpMainloop);
731 } catch (CAudioError e) {
732 if (isInThread() == false) {
733 pa_threaded_mainloop_unlock(mpMainloop);
741 CPulseAudioClient::EStreamDirection CPulseAudioClient::getStreamDirection() {
745 CPulseStreamSpec CPulseAudioClient::getStreamSpec() {