Merge "seek expection handling bug" into tizen_2.2
[platform/framework/native/media.git] / src / FMedia_TonePlayerImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 #include <FMediaToneTypes.h>
19 #include <FBaseSysLog.h>
20 #include "FMedia_TonePlayerImpl.h"
21 #include "FMedia_ToneGenerator.h"
22 #include "FMedia_TonePlayerEvent.h"
23 #include "FMedia_TonePlayerEventArg.h"
24 #include "FMedia_AudioManagerConvert.h"
25
26 using namespace Tizen::Base;
27 using namespace Tizen::Base::Collection;
28 using namespace Tizen::Base::Runtime;
29
30 namespace Tizen { namespace Media
31 {
32
33 std::unique_ptr<Tizen::Base::Runtime::Mutex> _TonePlayerImpl::__pMutex;
34 bool _TonePlayerImpl::__isInstanceMutexInitialized = false;
35 int _TonePlayerImpl::__instanceCount = 0;
36
37 #define MAX_TONE_PLAYER_VOLUME 100
38 #define TONE_PLAYER_FEED_BUFFER_SIZE 1024
39
40 _TonePlayerImpl::_TonePlayerImpl(void)
41         : __pTonePlayerEventListener(null)
42         , __endOftoneReached(false)
43         , __tonePlayerOptimalBufferSize(0)
44         , __stop(false)
45         , __audioStreamtype(AUDIO_STREAM_TYPE_MEDIA)
46         ,       __interruptFlag(false)
47 {
48         __repeatCount = 0;
49         __tempRepeatCount = 0;
50         __toneListIndex = 0;
51         __volume = DEFAULT_TONE_PLAYER_VOLUME;
52         __minBufferSize = 0;
53         __tonePlayerState = TONE_PLAYER_STATE_IDLE;
54         __duration = 0;
55         __tobePlayedBuffCount = 0;
56         __sampleNumber = 0;
57         __endOftoneReached = false;
58         __endOftoneReachedArr[0] = false;
59         __endOftoneReachedArr[1] = false;
60         __audioOutHandle = null;
61
62         __sampleNumberArr[0] = 0;
63         __sampleNumberArr[1] = 0;
64
65         __tempRepeatCountArr[0] = 0;
66         __tempRepeatCountArr[1] = 0;
67
68         __toneListIndexArr[0] = 0;
69         __toneListIndexArr[1] = 0;
70
71         __pToneBuffer = null;
72 }
73
74
75 _TonePlayerImpl::~_TonePlayerImpl(void)
76 {
77         if ((__tonePlayerState == TONE_PLAYER_STATE_PLAYING) ||
78                 (__tonePlayerState == TONE_PLAYER_STATE_STOPPED) ||
79                 (__tonePlayerState == TONE_PLAYER_STATE_PAUSED) ||
80                 (__tonePlayerState == TONE_PLAYER_STATE_OPENED))
81         {
82                 Stop();
83                 Close();
84         }
85         else if (__tonePlayerState == TONE_PLAYER_STATE_ERROR)
86         {
87                 if (__audioOutHandle)
88                 {
89                         int ret = AUDIO_IO_ERROR_NONE;
90                         ret = audio_out_unset_interrupted_cb(__audioOutHandle);
91                         SysTryLog(NID_MEDIA, ret == AUDIO_IO_ERROR_NONE, "Failed to perform audio_out_unset_interrupted_cb operation with %x", ret);
92
93                         ret = audio_out_destroy(__audioOutHandle);
94                         __audioOutHandle = null;
95                         SysTryLog(NID_MEDIA, ret == AUDIO_IO_ERROR_NONE, "Failed to perform audio_out_destroy operation with %0x%x", ret);
96                 }
97         }
98
99         if (__pToneList.get())
100         {
101                 __pToneList->RemoveAll(true);
102         }
103
104         if (__tonePlayerState != TONE_PLAYER_STATE_IDLE)
105         {
106                 __pMutex->Acquire();
107                 __instanceCount--;
108                 __pMutex->Release();
109         }
110         __tonePlayerState = TONE_PLAYER_STATE_IDLE;
111 }
112
113 void
114 _TonePlayerImpl::InitInstanceMutex(void)
115 {
116         result r = E_SUCCESS;
117         __pMutex.reset(new (std::nothrow) Tizen::Base::Runtime::Mutex);
118         SysTryReturn(NID_MEDIA, __pMutex.get() != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] no memory to create instance Mutex");
119         r = __pMutex->Create("FMEDIA_TONEPLAYER");
120         SysTryReturn(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Mutex::Create failed.");
121         __isInstanceMutexInitialized  = true;
122 }
123
124 _TonePlayerImpl*
125 _TonePlayerImpl::GetInstance(TonePlayer* pTonePlayer)
126 {
127         if (pTonePlayer != null)
128         {
129                 return pTonePlayer->__pTonePlayerImpl;
130         }
131
132         return null;
133 }
134
135 const _TonePlayerImpl*
136 _TonePlayerImpl::GetInstance(const TonePlayer* pTonePlayer)
137 {
138         if (pTonePlayer != null)
139         {
140                 return pTonePlayer->__pTonePlayerImpl;
141         }
142
143         return null;
144 }
145
146 result
147 _TonePlayerImpl::Construct(const Tizen::Media::ITonePlayerEventListener& listener, const Tizen::Media::TonePlayer& tonePlayerInstance)
148 {
149         result r = E_SUCCESS;
150         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
151         if (!__isInstanceMutexInitialized)
152         {
153                 pthread_once(&onceBlock, InitInstanceMutex);
154         }
155         SysTryCatch(NID_MEDIA, __isInstanceMutexInitialized == true, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] memory allocation for Instance Mutex failed");
156
157         SysTryCatch(NID_MEDIA, __tonePlayerState == TONE_PLAYER_STATE_IDLE ,
158                                                                                         r = E_INVALID_STATE, E_INVALID_STATE, " [E_INVALID_STATE] TonePlayer state is in an invalid state.");
159         SysTryCatch(NID_MEDIA, __instanceCount <= MAX_TONE_PLAYER_OUT_CAPACITY, r = E_RESOURCE_UNAVAILABLE, E_RESOURCE_UNAVAILABLE,
160                                                                                         "[E_RESOURCE_UNAVAILABLE] TonePlayer Exceeds the number of Instance available");
161
162         //Create TonePlayerEvent
163         __pTonePlayerEvent.reset(new (std::nothrow) _TonePlayerEvent);
164         SysTryCatch(NID_MEDIA, __pTonePlayerEvent.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, " [E_OUT_OF_MEMORY] Memory allocation failed.");
165         r = __pTonePlayerEvent->Construct(tonePlayerInstance);
166         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to construct _TonePlayerEvent.", GetErrorMessage(r));
167         r = __pTonePlayerEvent->AddListener(listener);
168         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
169
170         __pTonePlayerWorker.reset(new (std::nothrow) _TonePlayerWorker);
171         SysTryCatch(NID_MEDIA, __pTonePlayerWorker.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, " [E_OUT_OF_MEMORY] Memory allocation failed.");
172         __pTonePlayerWorker->Initialize(this);
173
174         __pMutex->Acquire();
175         __instanceCount++;
176         __pMutex->Release();
177
178         //Set State
179         __tonePlayerState = TONE_PLAYER_STATE_INITIALIZED;
180         return E_SUCCESS;
181 CATCH:
182         return r;
183 }
184
185 result
186 _TonePlayerImpl::SetAudioStreamType(AudioStreamType type)
187 {
188         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_INITIALIZED ) || (__tonePlayerState == TONE_PLAYER_STATE_CLOSED ),
189                                                                                                 E_INVALID_STATE, "TonePlayer instance is in an invalid state. State is %d", __tonePlayerState);
190
191         SysTryReturnResult(NID_MEDIA, (type != AUDIO_STREAM_TYPE_NO_SOUND )
192                                         , E_INVALID_ARG, "Invalid argument is used. AudioStream type = %d", type);
193
194         __audioStreamtype = type;
195         return E_SUCCESS;
196 }
197
198 result
199 _TonePlayerImpl::Open(const Tizen::Base::Collection::IList& toneList, int repeatCount)
200 {
201         result r = E_SUCCESS;
202         int firstFrequency = 0;
203         int secondFrequency = 0;
204         int duration = 0;
205         int  toneListCount = 0;
206         const Tone* pToneTemp = null;
207         Tone* pTone = null;
208         int ret = AUDIO_IO_ERROR_NONE;
209
210         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_INITIALIZED ) || (__tonePlayerState == TONE_PLAYER_STATE_CLOSED ),
211                                                                                 E_INVALID_STATE, "TonePlayer instance is in an invalid state. State is %d", __tonePlayerState);
212
213         SysTryReturnResult(NID_MEDIA, (repeatCount >= 1), E_OUT_OF_RANGE, "repeatCount is out of range should be greater than or equal to 1");
214
215         toneListCount = toneList.GetCount();
216
217         SysTryReturnResult(NID_MEDIA, (toneListCount >= 1), E_OBJ_NOT_FOUND, "Tone instance is not available.");
218
219         if (__pToneList.get())
220         {
221                 __pToneList->RemoveAll(true);
222         }
223         __pToneList.reset(new (std::nothrow) Tizen::Base::Collection::ArrayList);
224         SysTryReturnResult(NID_MEDIA, __pToneList.get() != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
225
226         r = __pToneList->Construct();
227         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to construct __pToneList..", GetErrorMessage(r));
228
229         for (int i = 0; i < toneListCount; i++)
230         {
231                 pToneTemp = dynamic_cast<const Tone*>(toneList.GetAt(i));
232                 SysTryCatch(NID_MEDIA, (pToneTemp != null), r = E_OBJ_NOT_FOUND, E_OBJ_NOT_FOUND, "[E_OBJ_NOT_FOUND] Tone instance is not available");
233
234                 r = pToneTemp->GetFrequency(firstFrequency, secondFrequency);
235                 SysTryCatch(NID_MEDIA, ((firstFrequency >= MIN_FREQUENCY) && (firstFrequency <= MAX_FREQUENCY)
236                 && (secondFrequency >= MIN_FREQUENCY) && (secondFrequency <= MAX_FREQUENCY)), r = E_OUT_OF_RANGE , E_OUT_OF_RANGE,
237                 "[E_OUT_OF_RANGE] firstFrequency and secondFrequency are out of range. firstFrequency = %d secondFrequency = %d.", firstFrequency, secondFrequency);
238
239                 duration = pToneTemp->GetDuration();
240
241                 // Adding parameters checker
242
243                 SysTryCatch(NID_MEDIA, (duration >= MIN_DURATION), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Duration is out of range - %d should be greater than or equal to %d", duration, MIN_DURATION);
244
245                 pTone = new (std::nothrow) Tone(firstFrequency, secondFrequency, duration);
246                 SysTryCatch(NID_MEDIA, pTone, r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[%s] Memory allocation failed.", GetErrorMessage(r));
247
248                 r = __pToneList->Add(*pTone);
249                 if (E_SUCCESS != r)
250                 {
251                         delete pTone;
252                 }
253                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
254         }
255
256         __repeatCount = repeatCount;
257
258         //Initilaize audio_out Device for raw audio out playback
259         ret = audio_out_create(SAMPLING_RATE, AUDIO_CHANNEL_MONO, AUDIO_SAMPLE_TYPE_S16_LE, _AudioManagerConvert::ConvertAudioStreamType2SoundType(__audioStreamtype), &__audioOutHandle);
260         r = MapExceptionToResult(ret);
261         SysTryCatch(NID_MEDIA, r != E_INVALID_STATE, , r, "[%s] The device has moved to invalid state as it has run out of system resources: 0x%x", GetErrorMessage(r), ret);
262         SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r, "[%s] Failed to perform audio_out_create operation with 0x%x", GetErrorMessage(r), ret);
263
264         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
265         r = MapExceptionToResult(ret);
266         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_set_interrupted_cb operation with 0x%x", GetErrorMessage(r), ret);
267
268         ret = audio_out_get_buffer_size(__audioOutHandle, &__tonePlayerOptimalBufferSize);
269         if (ret == AUDIO_IO_ERROR_NONE)
270         {
271                 SysLog(NID_MEDIA, "Optimal Buffer size is %d", __tonePlayerOptimalBufferSize);
272         }
273         else
274         {
275                 r = MapExceptionToResult(ret);
276                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with 0x%x",GetErrorMessage(r), ret);
277         }
278
279         __tonePlayerOptimalBufferSize = TONE_PLAYER_FEED_BUFFER_SIZE;
280
281         __pToneBuffer.reset(new (std::nothrow) ByteBuffer);
282         SysTryCatch(NID_MEDIA, __pToneBuffer.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
283         r = __pToneBuffer->Construct(__tonePlayerOptimalBufferSize);
284         SysTryCatch(NID_MEDIA, (r == E_SUCCESS), , r, "[%s] Failed to construct __pToneBuffer.", GetErrorMessage(r));
285
286         __tonePlayerState = TONE_PLAYER_STATE_OPENED;
287         return r;
288 CATCH:
289         //Clean Up audio-out Device
290         if (__audioOutHandle)
291         {
292                 ret = audio_out_unset_interrupted_cb(__audioOutHandle);
293                 r = MapExceptionToResult(ret);
294                 SysTryReturnResult(NID_MEDIA, r == E_SUCCESS, r, "Failed to perform audio_out_unset_interrupted_cb operation with %x", ret);
295
296                 ret = audio_out_destroy(__audioOutHandle);
297                 __audioOutHandle = null;
298                 r = MapExceptionToResult(ret);
299                 SysTryReturnResult(NID_MEDIA, r == E_SUCCESS, r, "Failed to perform audio_out_destroy operation with %0x%x", ret);
300         }
301
302         //Clean up Tones
303         if (__pToneList.get())
304         {
305                 __pToneList->RemoveAll(true);
306         }
307         return r;
308 }
309
310 result
311 _TonePlayerImpl::Open(const Tizen::Media::Tone& tone, int repeatCount)
312 {
313         result r = E_SUCCESS;
314         int firstFrequency = 0;
315         int secondFrequency = 0;
316         int duration = 0;
317         int ret = AUDIO_IO_ERROR_NONE;
318
319         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_INITIALIZED ) || (__tonePlayerState == TONE_PLAYER_STATE_CLOSED ), E_INVALID_STATE, "TonePlayer is in invalid state");
320
321         SysTryReturnResult(NID_MEDIA, (repeatCount >= 1), E_OUT_OF_RANGE, "repeatCount is out of range. repeatCount = %d.", repeatCount);
322
323         r = tone.GetFrequency(firstFrequency, secondFrequency);
324         SysTryReturnResult(NID_MEDIA, ((firstFrequency >= MIN_FREQUENCY) && (firstFrequency <= MAX_FREQUENCY)
325         && (secondFrequency >= MIN_FREQUENCY) && (secondFrequency <= MAX_FREQUENCY)) , E_OUT_OF_RANGE,
326         "firstFrequency and secondFrequency are out of range. firstFrequency = %d secondFrequency = %d.", firstFrequency, secondFrequency);
327
328         duration = tone.GetDuration();
329
330         // Adding parameters checker
331         SysTryCatch(NID_MEDIA, (duration >= MIN_DURATION), r = E_OUT_OF_RANGE, E_OUT_OF_RANGE, "[E_OUT_OF_RANGE] Duration is out of range");
332
333
334         __pTone.reset(new (std::nothrow) Tone(firstFrequency, secondFrequency, duration));
335         SysTryReturnResult(NID_MEDIA, __pTone.get() != null, E_OUT_OF_MEMORY, "Memory allocation failed.");
336
337         __repeatCount = repeatCount;
338         //Initlaize audio-out Device for raw audio out playback
339         ret = audio_out_create(SAMPLING_RATE, AUDIO_CHANNEL_MONO, AUDIO_SAMPLE_TYPE_S16_LE, _AudioManagerConvert::ConvertAudioStreamType2SoundType(__audioStreamtype), &__audioOutHandle);
340         SysTryCatch(NID_MEDIA, r != E_INVALID_STATE, , r, "[%s] The device has moved to invalid state as it has run out of system resources: 0x%x", GetErrorMessage(r), ret);
341         r = MapExceptionToResult(ret);
342         SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r, "[%s] Failed to perform audio_out_create operation with 0x%x", GetErrorMessage(r), ret);
343
344         ret = audio_out_set_interrupted_cb(__audioOutHandle, AudioIoInterrupted, this);
345         r = MapExceptionToResult(ret);
346         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_set_interrupted_cb operation with 0x%x", GetErrorMessage(r), ret);
347
348         ret = audio_out_get_buffer_size(__audioOutHandle, &__tonePlayerOptimalBufferSize);
349         if (ret == AUDIO_IO_ERROR_NONE)
350         {
351                 SysLog(NID_MEDIA, "Optimal Buffer size is %d", __tonePlayerOptimalBufferSize);
352         }
353         else
354         {
355                 r = MapExceptionToResult(ret);
356                 SysLogException(NID_MEDIA, r, "[%s] Failed to perform audio_out_get_buffer_size operation with 0x%x", GetErrorMessage(r), ret);
357         }
358
359         __tonePlayerOptimalBufferSize = TONE_PLAYER_FEED_BUFFER_SIZE;
360
361         __pToneBuffer.reset(new (std::nothrow) ByteBuffer);
362         SysTryCatch(NID_MEDIA, __pToneBuffer.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
363         r = __pToneBuffer->Construct(__tonePlayerOptimalBufferSize);
364         SysTryCatch(NID_MEDIA, (r == E_SUCCESS), , r, "[%s] Failed to construct __pToneBuffer.", GetErrorMessage(r));
365
366         __tonePlayerState = TONE_PLAYER_STATE_OPENED;
367         return r;
368
369 CATCH:
370         if (__audioOutHandle)
371         {
372                 ret = audio_out_unset_interrupted_cb(__audioOutHandle);
373                 r = MapExceptionToResult(ret);
374                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to perform audio_out_unset_interrupted_cb operation with %x", GetErrorMessage(r), ret);
375
376                 ret = audio_out_destroy(__audioOutHandle);
377                 r = MapExceptionToResult(ret);
378                 SysTryReturnResult(NID_MEDIA, r == E_SUCCESS, r, "Failed to perform audio_out_destroy operation with 0x%x", ret);
379
380                 __audioOutHandle = null;
381         }
382         return r;
383 }
384
385
386 result
387 _TonePlayerImpl::Play(void)
388 {
389         result r = E_SUCCESS;
390         int ret = AUDIO_IO_ERROR_NONE;
391         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_PAUSED ) ||
392                                           (__tonePlayerState == TONE_PLAYER_STATE_OPENED) ||
393                                           (__tonePlayerState == TONE_PLAYER_STATE_STOPPED ), E_INVALID_STATE, "TonePlayer is in an invalid state - %d", __tonePlayerState);
394
395         if ((__tonePlayerState == TONE_PLAYER_STATE_OPENED ) || (__tonePlayerState == TONE_PLAYER_STATE_STOPPED ))
396         {
397                 __tempRepeatCount = __repeatCount;
398                 __tempRepeatCountArr[0] = __tempRepeatCount;
399                 __tempRepeatCountArr[1] = __tempRepeatCount;
400
401                 __tobePlayedBuffCount = 0;
402
403                 __sampleNumber = 0;
404                 __sampleNumberArr[0] = __sampleNumber;
405                 __sampleNumberArr[1] = __sampleNumber;
406
407                 __endOftoneReached = false;
408                 __endOftoneReachedArr[0] = __endOftoneReached;
409                 __endOftoneReachedArr[1] = __endOftoneReached;
410
411                 if (__pToneList.get())
412                 {
413                         __toneListIndex = __pToneList->GetCount();
414                         __toneListIndexArr[0] = __toneListIndex;
415                         __toneListIndexArr[1] = __toneListIndex;
416                 }
417                 __stop = false;
418
419                 ret = audio_out_prepare(__audioOutHandle);
420                 r = MapExceptionToResult(ret);
421                 SysTryReturnResult(NID_MEDIA, r != E_DEVICE_BUSY, r, "TonePlayer cannot Start, higher priority task at work.");
422                 SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r, "[%s] Failed to perform audio_out_prepare operation with 0x%x", GetErrorMessage(r), ret);
423
424                 __pWorkerThread.reset(new (std::nothrow) Thread);
425                 SysTryCatch(NID_MEDIA, __pWorkerThread.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
426                 r = __pWorkerThread->Construct(*(__pTonePlayerWorker.get()));
427                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to construct __pWorkerThread.", GetErrorMessage(r));
428                 r = __pWorkerThread->Start();
429                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
430
431         }
432         else if ((__tonePlayerState == TONE_PLAYER_STATE_PAUSED ))
433         {
434                 __tempRepeatCount = __tempRepeatCountArr[0];
435                 __sampleNumber = __sampleNumberArr[0];
436                 __endOftoneReached = __endOftoneReachedArr[0];
437
438                 if (__pToneList.get())
439                 {
440                         __toneListIndex = __toneListIndexArr[0];
441                 }
442                 __stop = false;
443
444                 ret = audio_out_prepare(__audioOutHandle);
445                 r = MapExceptionToResult(ret);
446                 SysTryReturnResult(NID_MEDIA, r != E_DEVICE_BUSY, r, "TonePlayer cannot Start, higher priority task at work.");
447                 SysTryCatch(NID_MEDIA, r == E_SUCCESS , , r, "[%s] Failed to perform audio_out_prepare operation with 0x%x", GetErrorMessage(r), ret);
448
449                 __pWorkerThread.reset(new (std::nothrow) Thread);
450                 SysTryCatch(NID_MEDIA, __pWorkerThread.get(), r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] Memory allocation failed.");
451                 r = __pWorkerThread->Construct(*(__pTonePlayerWorker.get()));
452                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Failed to construct __pWorkerThread..", GetErrorMessage(r));
453                 r = __pWorkerThread->Start();
454                 SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagating.", GetErrorMessage(r));
455         }
456         //Set the State
457         __tonePlayerState = TONE_PLAYER_STATE_PLAYING;
458         return r;
459
460 CATCH:
461         __tonePlayerState = TONE_PLAYER_STATE_ERROR;
462         return r;
463 }
464
465
466 result
467 _TonePlayerImpl::Stop(void)
468 {
469         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_PAUSED ) ||
470                                           (__tonePlayerState == TONE_PLAYER_STATE_PLAYING ), E_INVALID_STATE, "TonePlayer is in an invalid state");
471         result r = E_SUCCESS;
472         int ret = AUDIO_IO_ERROR_NONE;
473         __stop = true;
474         if (__pWorkerThread.get())
475         {
476                 __pWorkerThread->Join();
477                 __pWorkerThread.reset(null);
478         }
479
480         if (__tonePlayerState == TONE_PLAYER_STATE_PLAYING)
481         {
482                 ret = audio_out_unprepare(__audioOutHandle);
483                 r = MapExceptionToResult(ret);
484                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Failed to perform audio_out_unprepare operation with 0x%x", GetErrorMessage(r), ret);
485         }
486         __tonePlayerState = TONE_PLAYER_STATE_STOPPED;
487
488         return r;
489 }
490
491 result
492 _TonePlayerImpl::Pause(void)
493 {
494         result r = E_SUCCESS;
495         int ret = AUDIO_IO_ERROR_NONE;
496         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_PLAYING ), E_INVALID_STATE,
497                                         "TonePlayer instance is in an invalid state. State is %d", __tonePlayerState);
498         __stop = true;
499
500         if (__pWorkerThread.get())
501         {
502                 __pWorkerThread->Join();
503                 __pWorkerThread.reset(null);
504         }
505
506         ret = audio_out_unprepare(__audioOutHandle);
507         r = MapExceptionToResult(ret);
508         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Failed to perform audio_out_unprepare operation with 0x%x", GetErrorMessage(r), ret);
509
510         __tonePlayerState = TONE_PLAYER_STATE_PAUSED;
511         return r;
512 }
513
514
515 result
516 _TonePlayerImpl::Close(void)
517 {
518         result r = E_SUCCESS;
519         SysTryReturnResult(NID_MEDIA, (__tonePlayerState == TONE_PLAYER_STATE_OPENED ) || (__tonePlayerState == TONE_PLAYER_STATE_STOPPED ) ||
520                                                 (__tonePlayerState == TONE_PLAYER_STATE_END_OF_TONE ), E_INVALID_STATE, "TonePlayer is in an invalid state");
521
522         if (__tonePlayerState == TONE_PLAYER_STATE_END_OF_TONE)
523         {
524                 __stop = true;
525                 if (__pWorkerThread.get())
526                 {
527                         SysLog(NID_MEDIA, "Join is starting.");
528                         __pWorkerThread->Join();
529                 }
530         }
531         __tonePlayerState = TONE_PLAYER_STATE_CLOSED;
532
533         if (__audioOutHandle)
534         {
535                 int ret = AUDIO_IO_ERROR_NONE;
536                 ret = audio_out_unset_interrupted_cb(__audioOutHandle);
537                 r = MapExceptionToResult(ret);
538                 SysTryLog(NID_MEDIA, r == E_SUCCESS,"[%s] Failed to perform audio_out_unset_interrupted_cb operation with %x", GetErrorMessage(r), ret);
539
540                 ret = audio_out_destroy(__audioOutHandle);
541                 __audioOutHandle = null;
542                 r = MapExceptionToResult(ret);
543                 SysTryLog(NID_MEDIA, r == E_SUCCESS , "[%s] Failed to perform audio_out_destroy operation with %0x%x", GetErrorMessage(r), ret);
544         }
545
546         if (__pToneList.get() != null)
547         {
548                 __pToneList->RemoveAll(true);
549         }
550         return r;
551 }
552
553 result
554 _TonePlayerImpl::SetVolume(int& volume)
555 {
556         result r = E_SUCCESS;
557         SysTryReturnResult(NID_MEDIA, (0 <= volume) && (volume <= MAX_TONE_PLAYER_VOLUME), E_OUT_OF_RANGE,
558                                                                                                                 "volume is out of range. volume = %d", volume);
559         __volume = volume;
560         return r;
561 }
562
563 int
564 _TonePlayerImpl::GetVolume(void) const
565 {
566         SetLastResult(E_SUCCESS);
567         return __volume;
568 }
569
570
571 TonePlayerState
572 _TonePlayerImpl::GetState(void) const
573 {
574         SetLastResult(E_SUCCESS);
575         return __tonePlayerState;
576 }
577
578 void
579 _TonePlayerImpl::Feed(void)
580 {
581         int buffer_size = 0;
582         unsigned char* pData = NULL;
583         result r = E_SUCCESS;
584         int ret = AUDIO_IO_ERROR_NONE;
585         bool isSuccesful = true;
586         while (!__stop)
587         {
588                 if (isSuccesful)
589                 {
590                         __pToneBuffer->Clear();
591                         if (!GetBuffer(*__pToneBuffer.get()))
592                         {
593                                 __tonePlayerState = TONE_PLAYER_STATE_END_OF_TONE;
594                                 r = SendEndOfTone();
595                                 SysTryReturnVoidResult(NID_MEDIA, r == E_SUCCESS, r, "[%s] Propagating.", GetErrorMessage(r));
596                                 return;
597                         }
598                         isSuccesful = false;
599                 }
600                 buffer_size = __pToneBuffer->GetLimit();
601                 pData = (unsigned char*) __pToneBuffer->GetPointer();
602                 SysTryCatch(NID_MEDIA, pData, r = E_INVALID_ARG, E_INVALID_ARG, "[E_INVALID_ARG] Invalid argument is used. Data Sent to TonePlayer is null");
603                 if (!__stop)
604                 {
605                         ret = audio_out_write(__audioOutHandle, (void*) pData, buffer_size);
606                         if (ret != buffer_size)
607                         {
608                                 //wrong;
609                                 SysLog(NID_MEDIA, "Audio Device could only put %d data to device", ret);
610                         }
611                         else
612                         {
613                                 isSuccesful = true;
614                         }
615                 }
616         }
617         return;
618 CATCH:
619         SendError(r);
620         return;
621 }
622
623 void
624 _TonePlayerImpl::AudioIoInterrupted(audio_io_interrupted_code_e code, void *pUserData)
625 {
626         SysTryReturn(NID_MEDIA, pUserData, , E_SYSTEM, "[E_SYSTEM] A system error has been occurred. pUserData is null.");
627         _TonePlayerImpl *pTonePlayerImpl = (_TonePlayerImpl *)pUserData;
628
629         switch(code)
630         {
631         case AUDIO_IO_INTERRUPTED_COMPLETED:
632                 if (pTonePlayerImpl->__tonePlayerState == TONE_PLAYER_STATE_PAUSED || pTonePlayerImpl->__tonePlayerState == TONE_PLAYER_STATE_STOPPED)
633                 {
634                         if (!(pTonePlayerImpl->__interruptFlag))
635                         {
636                                 pTonePlayerImpl->SendReleased();
637                         }
638                         pTonePlayerImpl->__interruptFlag = false;
639                 }
640                 break;
641         case AUDIO_IO_INTERRUPTED_BY_CALL:
642                 pTonePlayerImpl->__interruptFlag = true;
643                 //Intentional Fall through
644         case AUDIO_IO_INTERRUPTED_BY_EARJACK_UNPLUG:
645                 //Intentional Fall through
646         case AUDIO_IO_INTERRUPTED_BY_MEDIA:
647                 //Intentional Fall through
648         case AUDIO_IO_INTERRUPTED_BY_RESOURCE_CONFLICT:
649                 if (pTonePlayerImpl->__tonePlayerState == TONE_PLAYER_STATE_PLAYING)
650                 {
651                         pTonePlayerImpl->SendAudioFocusChanged();
652                 }
653                 break;
654         case AUDIO_IO_INTERRUPTED_BY_ALARM:
655                 //Intentional Fall through
656         case AUDIO_IO_INTERRUPTED_BY_EMERGENCY:
657                 //Intentional Fall through
658         case AUDIO_IO_INTERRUPTED_BY_RESUMABLE_MEDIA:
659                 if (pTonePlayerImpl->__tonePlayerState == TONE_PLAYER_STATE_PLAYING)
660                 {
661                         pTonePlayerImpl->SendInterrupted();
662                 }
663                 break;
664         default:
665                 SysLog(NID_MEDIA, "Audio I/O Interrupt is not set.");
666                 break;
667         }
668 }
669
670 bool
671 _TonePlayerImpl::GetBuffer(Tizen::Base::ByteBuffer& toneBuffer)
672 {
673         int bufferTobeFilledSize = __tonePlayerOptimalBufferSize;
674         int firstFrequency = 0;
675         int secondFrequency = 0;
676         long startSample = 0;
677         long endSample = 0;
678
679         toneBuffer.Clear();
680
681         __sampleNumberArr[0] = __sampleNumberArr[1];
682         __sampleNumberArr[1] = __sampleNumber;
683
684         __tempRepeatCountArr[0] = __tempRepeatCountArr[1];
685         __tempRepeatCountArr[1] = __tempRepeatCount;
686
687         __toneListIndexArr[0] = __toneListIndexArr[1];
688         __toneListIndexArr[1] = __toneListIndex;
689
690         __endOftoneReachedArr[0] = __endOftoneReachedArr[1];
691         __endOftoneReachedArr[1] = __endOftoneReached;
692
693         // If already end of tone is reached generate silent buffer and return
694         if (__endOftoneReached)
695         {
696                 bufferTobeFilledSize = __tonePlayerOptimalBufferSize - toneBuffer.GetPosition(); //buffer size to be filled is total size - already filled buffer size
697                 firstFrequency = 0;
698                 secondFrequency = 0;
699                 _ToneGenerator::GenerateTone(toneBuffer, firstFrequency, secondFrequency, 0, bufferTobeFilledSize / _BYTES_PER_SAMPLE, __volume); //fill silent buffer
700                 return false;
701         }
702
703         while (1)
704         {
705                 // Get the details of the buffer to be generated
706                 if (!GetNextToneBufferDetails(bufferTobeFilledSize, firstFrequency, secondFrequency, startSample, endSample))
707                 {
708                         __endOftoneReached = true;
709                         _ToneGenerator::GenerateTone(toneBuffer, firstFrequency, secondFrequency, startSample, endSample, __volume);
710                         bufferTobeFilledSize = __tonePlayerOptimalBufferSize - toneBuffer.GetPosition();
711                         firstFrequency = 0;
712                         secondFrequency = 0;
713                         _ToneGenerator::GenerateTone(toneBuffer, firstFrequency, secondFrequency, 0, bufferTobeFilledSize / _BYTES_PER_SAMPLE, __volume); //fill silent buffer
714                         return false;
715                 }
716                 _ToneGenerator::GenerateTone(toneBuffer, firstFrequency, secondFrequency, startSample, endSample, __volume);
717                 bufferTobeFilledSize = __tonePlayerOptimalBufferSize - toneBuffer.GetPosition();
718
719                 // keep trying till the buffer gets filled
720                 if (0 >= bufferTobeFilledSize)
721                 {
722                         return true;
723                 }
724
725         }
726         return true;
727 }
728
729 bool
730 _TonePlayerImpl::GetNextToneBufferDetails(int bufferTobeFilledSize, int& firstFrequency, int& secondFrequency, long& startSample, long& endSample)
731 {
732         bufferTobeFilledSize /= _BYTES_PER_SAMPLE;
733
734         // This case is for construct with just Tone
735         if (__pToneList.get() == null)
736         {
737                 __pTone->GetFrequency(firstFrequency, secondFrequency);
738                 __duration = __pTone->GetDuration();
739
740                 if ((__sampleNumber + bufferTobeFilledSize) <= (int) (SAMPLING_RATE / 1000.0 * __duration)) //(SAMPLING_RATE/1000.0*__duration)) gives the total samples for the duration
741                 {
742                         startSample = __sampleNumber;
743                         __sampleNumber += bufferTobeFilledSize; // if current sample number is less than total sample return samples to be generated
744                         endSample = __sampleNumber;
745                         return true;
746                 }
747                 else
748                 {
749                         startSample = __sampleNumber;
750                         endSample = (int) (SAMPLING_RATE / 1000.0 * __duration);
751                         __tempRepeatCount--;
752                         __sampleNumber = 0;
753                         if (0 >= __tempRepeatCount)
754                         {
755                                 return false;
756                         }
757                         else
758                         {
759                                 return true;
760                         }
761                 }
762         }
763         else        // Construct with Tone List
764         {
765                 Tone* pTone = dynamic_cast<Tone*>(__pToneList->GetAt(__pToneList->GetCount() - __toneListIndex));
766
767                 if (pTone == null)
768                 {
769                         SysLog(NID_MEDIA, "pTone is null");
770                         return false;
771                 }
772
773                 pTone->GetFrequency(firstFrequency, secondFrequency);
774                 __duration = pTone->GetDuration();
775
776                 if ((__sampleNumber + bufferTobeFilledSize) <= (int) (SAMPLING_RATE / 1000.0 * __duration))
777                 {
778                         startSample = __sampleNumber;
779                         __sampleNumber += bufferTobeFilledSize;
780                         endSample = __sampleNumber;
781                         return true;
782                 }
783                 else
784                 {
785                         startSample = __sampleNumber;
786                         endSample = (int) (SAMPLING_RATE / 1000.0 * __duration);
787                         __toneListIndex--;
788                         __sampleNumber = 0;
789                         if (0 >= __toneListIndex)
790                         {
791                                 __tempRepeatCount--;
792                                 if (0 >= __tempRepeatCount)
793                                 {
794                                         return false;
795                                 }
796                                 else
797                                 {
798                                         __toneListIndex = __pToneList->GetCount();
799                                         return true;
800                                 }
801                         }
802                         else
803                         {
804                                 return true;
805                         }
806                 }
807         }
808         return false;
809 }
810
811 result
812 _TonePlayerImpl::SendEndOfTone(void)
813 {
814         result r = E_SUCCESS;
815         int ret = AUDIO_IO_ERROR_NONE;
816
817         ret = audio_out_unprepare(__audioOutHandle);
818         r = MapExceptionToResult(ret);
819         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Failed to perform audio_out_unprepare operation with 0x%x", GetErrorMessage(r), ret);
820
821         _TonePlayerEventArg* pTonePlayerEventArg = null;
822         pTonePlayerEventArg = new (std::nothrow) _TonePlayerEventArg;
823         SysTryReturnResult(NID_MEDIA, pTonePlayerEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
824         pTonePlayerEventArg->SetEventType(_TONEPLAYER_EVENT_END_OF_PLAY_REACHED);
825         r = __pTonePlayerEvent->FireAsync(*pTonePlayerEventArg);
826         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
827         return r;
828 CATCH:
829         delete pTonePlayerEventArg;
830         pTonePlayerEventArg = null;
831
832         return r;
833 }
834
835 result
836 _TonePlayerImpl::SendInterrupted(void)
837 {
838         result r = E_SUCCESS;
839         _TonePlayerEventArg* pTonePlayerEventArg = null;
840         pTonePlayerEventArg = new (std::nothrow) _TonePlayerEventArg;
841         SysTryReturnResult(NID_MEDIA, pTonePlayerEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
842         this->Pause();
843         pTonePlayerEventArg->SetEventType(_TONEPLAYER_EVENT_INTERRUPTED);
844         r = __pTonePlayerEvent->FireAsync(*pTonePlayerEventArg);
845         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
846         return r;
847 CATCH:
848         delete pTonePlayerEventArg;
849         pTonePlayerEventArg = null;
850
851         return r;
852 }
853
854 result
855 _TonePlayerImpl::SendAudioFocusChanged(void)
856 {
857         result r = E_SUCCESS;
858         _TonePlayerEventArg* pTonePlayerEventArg = null;
859         pTonePlayerEventArg = new (std::nothrow) _TonePlayerEventArg;
860         SysTryReturnResult(NID_MEDIA, pTonePlayerEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
861         this->Pause();
862         pTonePlayerEventArg->SetEventType(_TONEPLAYER_EVENT_AUDIO_FOCUS_CHAGNED);
863         r = __pTonePlayerEvent->FireAsync(*pTonePlayerEventArg);
864         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
865         return r;
866 CATCH:
867         delete pTonePlayerEventArg;
868         pTonePlayerEventArg = null;
869
870         return r;
871 }
872
873 result
874 _TonePlayerImpl::SendReleased(void)
875 {
876         result r = E_SUCCESS;
877         _TonePlayerEventArg* pTonePlayerEventArg = null;
878         pTonePlayerEventArg = new (std::nothrow) _TonePlayerEventArg;
879         SysTryReturnResult(NID_MEDIA, pTonePlayerEventArg, E_OUT_OF_MEMORY, "Memory allocation failed.");
880         pTonePlayerEventArg->SetEventType(_TONEPLAYER_EVENT_RELEASED);
881         r = __pTonePlayerEvent->FireAsync(*pTonePlayerEventArg);
882         SysTryCatch(NID_MEDIA, r == E_SUCCESS, r = GetLastResult(), r, "[%s] Propagating.", GetErrorMessage(r));
883         return r;
884 CATCH:
885         delete pTonePlayerEventArg;
886         pTonePlayerEventArg = null;
887
888         return r;
889 }
890
891 result
892 _TonePlayerImpl::SendError(result reason)
893 {
894         result r = E_SUCCESS;
895         __tonePlayerState = TONE_PLAYER_STATE_ERROR;
896         _TonePlayerErrorArg* pTonePlayerErrorArg = NULL;
897
898         pTonePlayerErrorArg = new (std::nothrow) _TonePlayerErrorArg;
899         if (pTonePlayerErrorArg == null)
900         {
901                 r = E_OUT_OF_MEMORY;
902                 goto CATCH_;
903         }
904         pTonePlayerErrorArg->SetEventType(_TONEPLAYER_EVENT_ERROR);
905         pTonePlayerErrorArg->SetError(reason);
906         r = __pTonePlayerEvent->FireAsync(*pTonePlayerErrorArg);
907         if (IsFailed(r))
908         {
909                 goto CATCH_;
910         }
911         return r;
912
913 CATCH_:
914         if (pTonePlayerErrorArg != null)
915         {
916                 delete pTonePlayerErrorArg;
917         }
918         return r;
919 }
920
921 result
922 _TonePlayerImpl::MapExceptionToResult(int reason)
923 {
924         //All the fall through are intentional
925         switch (reason)
926         {
927         //Successful
928         case AUDIO_IO_ERROR_NONE:
929                 return E_SUCCESS;
930                 break;
931         //Out of memory
932         case AUDIO_IO_ERROR_OUT_OF_MEMORY:
933                 return E_OUT_OF_MEMORY;
934                 break;
935         //Invalid parameter
936         case AUDIO_IO_ERROR_INVALID_PARAMETER:
937                 return E_INVALID_ARG;
938                 break;
939         //Invalid operation
940         case AUDIO_IO_ERROR_INVALID_OPERATION:
941                 return E_INVALID_OPERATION;
942                 break;
943         //device not opened
944         case AUDIO_IO_ERROR_DEVICE_NOT_OPENED:
945                 return E_INVALID_STATE;
946                 break;
947         //invalid buffer
948         case AUDIO_IO_ERROR_INVALID_BUFFER:
949                 return E_INVALID_ARG;
950                 break;
951         //device not closed
952         case AUDIO_IO_ERROR_DEVICE_NOT_CLOSED:
953                 return E_INVALID_STATE;
954                 break;
955         //Sound policy error
956         case AUDIO_IO_ERROR_SOUND_POLICY:
957                 return E_DEVICE_BUSY;
958                 break;
959         default:
960                 return E_SYSTEM;
961                 break;
962         }
963 }
964
965 };
966 };   //Tizen::Media