Fix double unlock of slot mutex in user stops scneario
[platform/core/multimedia/libmm-sound.git] / server / plugin / wav / mm_sound_plugin_codec_wave.c
index 933d5db..65ea459 100644 (file)
@@ -40,7 +40,7 @@
 typedef struct {
        int handle;
        int repeat_count;
-       int (*stop_cb)(int);
+       int (*stop_cb)(int, bool);
        char filename[MM_SOUND_MAX_FILENAME];
        int cb_param;
        char stream_type[MAX_STREAM_TYPE_LEN];
@@ -49,10 +49,12 @@ typedef struct {
 
        pa_threaded_mainloop *m;
        pa_context *c;
-       pa_streams;
+       pa_stream *s;
        pa_sample_spec spec;
-       SNDFILEsf;
+       SNDFILE *sf;
        SF_INFO si;
+
+       size_t written;
 } wave_info_t;
 
 static int _sound_prepare(wave_info_t *h)
@@ -198,15 +200,15 @@ static void _pa_stream_state_callback(pa_stream *s, void *userdata)
        }
 }
 
-static void _pa_stream_drain_complete_callback(pa_streams, int success, void *userdata)
+static void _pa_stream_drain_complete_callback(pa_stream *s, int success, void *userdata)
 {
        pa_operation *o = NULL;
        wave_info_t *h = (wave_info_t *)userdata;
 
-       debug_msg("drain complete : %p, %d", s, success);
+       debug_msg("stream(%p) : drain completed(%d)", s, success);
 
        if (!success) {
-               debug_error("drain failed. s(%p), success(%d)", s, success);
+               debug_error("stream(%p) : drain failed(%d)", s, success);
                //pa_threaded_mainloop_signal(h->m, 0);
        }
 
@@ -215,7 +217,7 @@ static void _pa_stream_drain_complete_callback(pa_stream* s, int success, void *
        h->s = NULL;
 
        if (!(o = pa_context_drain(h->c, _pa_context_drain_complete_callback, h->m))) {
-               debug_error("failed to drain context!");
+               debug_error("context(%p) failed to drain context!", h->c);
                pa_context_disconnect(h->c);
                pa_context_unref(h->c);
                h->c = NULL;
@@ -223,15 +225,15 @@ static void _pa_stream_drain_complete_callback(pa_stream* s, int success, void *
                pa_operation_unref(o);
        }
 
-       debug_msg("Call stop callback(%p, %d) of mgr_codec", h->stop_cb, h->cb_param);
+       debug_msg("Invoke stop callback(%p, %d) of mgr_codec", h->stop_cb, h->cb_param);
        if (h->stop_cb)
-               h->stop_cb(h->cb_param);
+               h->stop_cb(h->cb_param, false);
 }
 
 static void _pa_stream_moved_callback(pa_stream *s, void *userdata)
 {
        assert(s);
-       debug_msg("stream moved callback : %p", s);
+       debug_msg("stream(%p)", s);
 }
 
 static void _pa_stream_underflow_callback(pa_stream *s, void *userdata)
@@ -239,13 +241,19 @@ static void _pa_stream_underflow_callback(pa_stream *s, void *userdata)
        wave_info_t *h = (wave_info_t *)userdata;
        assert(s);
 
-       debug_msg("stream underflow callback : %p, file(%s)", s, h->filename);
+       debug_msg("stream(%p) : file(%s)", s, h->filename);
 }
 
 static void _pa_stream_buffer_attr_callback(pa_stream *s, void *userdata)
 {
        assert(s);
-       debug_msg("stream underflow callback : %p", s);
+       debug_msg("stream(%p)", s);
+}
+
+static void _pa_stream_started_callback(pa_stream *s, void *userdata)
+{
+       assert(s);
+       debug_msg("stream(%p)", s);
 }
 
 static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdata)
@@ -258,7 +266,7 @@ static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdat
        wave_info_t *h = (wave_info_t *)userdata;
 
        if (!s || length <= 0) {
-               debug_error("write error. stream(%p), length(%zu)", s, length);
+               debug_error("stream(%p) : length(%zu)", s, length);
                return;
        }
 
@@ -266,32 +274,34 @@ static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdat
        data_length = length;
 
        if (frame_size == 0) {
-               debug_error("frame size can't be 0");
+               debug_error("stream(%p) : frame size can't be 0", s);
                return;
        }
 
        if (pa_stream_begin_write(s, &data, &data_length) < 0) {
-               debug_error("failed to pa_stream_begin_write()");
+               debug_error("stream(%p) : failed to pa_stream_begin_write()", s);
                return;
        }
 
        if ((bytes = sf_readf_short(h->sf, data, (sf_count_t)(data_length / frame_size))) > 0)
                bytes *= (sf_count_t)frame_size;
 
-       debug_log("=== %"PRId64" / %zu ===", bytes, data_length);
+       debug_msg("stream(%p) : === %"PRId64" / %zu / %zu ===", s, bytes, data_length, h->written);
 
        if (bytes > 0)
                pa_stream_write(s, data, (size_t)bytes, NULL, 0, PA_SEEK_RELATIVE);
        else
                pa_stream_cancel_write(s);
 
+       h->written += bytes;
+
        /* If No more data, drain stream */
        if (bytes < (sf_count_t)data_length) {
-               debug_msg("EOS!!!!! %"PRId64"/%zu", bytes, data_length);
+               debug_msg("stream(%p) : End Of Stream", s);
 
                /* Handle loop */
                if (_sound_is_rewind_needed(h)) {
-                       debug_msg("repeat count = %d", h->repeat_count);
+                       debug_msg("stream(%p) : repeat count = %d", s, h->repeat_count);
                        /* do not decrease it in case of -1 for infinite play */
                        if (h->repeat_count != -1)
                                h->repeat_count--;
@@ -299,7 +309,7 @@ static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdat
                        if (_sound_rewind(h) == 0)
                                return;
 
-                       debug_error("REWIND failed....");
+                       debug_error("stream(%p) : REWIND failed....", s);
                        /* can't loop anymore, fallback and do drain */
                }
 
@@ -309,7 +319,8 @@ static void _pa_stream_write_callback(pa_stream *s, size_t length, void *userdat
                if (o)
                        pa_operation_unref(o);
                else
-                       debug_error("failed to drain stream %p", s);
+                       debug_error("stream(%p) : failed to drain", s);
+               debug_msg("stream(%p) : reset write callback and drain requested", s);
        }
 }
 
@@ -402,12 +413,13 @@ static int _pa_stream_connect(wave_info_t *h)
        pa_stream_set_moved_callback(s, _pa_stream_moved_callback, h);
        pa_stream_set_underflow_callback(s, _pa_stream_underflow_callback, h);
        pa_stream_set_buffer_attr_callback(s, _pa_stream_buffer_attr_callback, h);
+       pa_stream_set_started_callback(s, _pa_stream_started_callback, h);
 
        ret = pa_stream_connect_playback(s, NULL, NULL,
                PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_START_CORKED,
                NULL, NULL);
        if (ret < 0) {
-               debug_error("failed to pa_stream_connect_playback(), ret(%d)", ret);
+               debug_error("stream(%p) : failed to connect playback, ret(%d)", s, ret);
                goto error;
        }
        for (;;) {
@@ -417,7 +429,7 @@ static int _pa_stream_connect(wave_info_t *h)
                        break;
 
                if (!PA_STREAM_IS_GOOD(state)) {
-                       debug_error("Stream error!!!! %d", state);
+                       debug_error("stream(%p) : state(%d)", s, state);
                        goto error;
                }
 
@@ -453,7 +465,7 @@ static void _pa_stream_uncork(wave_info_t *h)
        if ((o = pa_stream_cork(h->s, 0, NULL, NULL)))
                pa_operation_unref(o);
        else
-               debug_error("stream uncork failed");
+               debug_error("stream(%p) : uncork failed", h->s);
 
        pa_threaded_mainloop_unlock(h->m);
 }
@@ -480,7 +492,7 @@ static void _pa_stream_stop_disconnect(wave_info_t *h)
        h->m = NULL;
 }
 
-static int* _mm_sound_plug_codec_wave_get_supported_types(void)
+static int * _mm_sound_plug_codec_wave_get_supported_types(void)
 {
        static int suported[2] = { MM_SOUND_SUPPORTED_CODEC_WAVE, 0 };
        return suported;
@@ -488,7 +500,7 @@ static int* _mm_sound_plug_codec_wave_get_supported_types(void)
 
 static int _mm_sound_plug_codec_wave_parse(const char *filename, mmsound_codec_info_t *info)
 {
-       SNDFILEsf = NULL;
+       SNDFILE *sf = NULL;
        SF_INFO si;
 
        if (!filename || !info) {
@@ -511,7 +523,7 @@ static int _mm_sound_plug_codec_wave_parse(const char *filename, mmsound_codec_i
        info->channels = si.channels;
        info->samplerate = si.samplerate;
 
-       debug_msg("filename = %s, frames[%"PRId64"], samplerate[%d], channels[%d], format[%x], sections[%d], seekable[%d]",
+       debug_msg("filename[%s], frames[%"PRId64"], samplerate[%d], channels[%d], format[%x], sections[%d], seekable[%d]",
                        filename, si.frames, si.samplerate, si.channels, si.format, si.sections, si.seekable);
        sf_close(sf);
 
@@ -520,103 +532,101 @@ static int _mm_sound_plug_codec_wave_parse(const char *filename, mmsound_codec_i
 
 static int _mm_sound_plug_codec_wave_create(mmsound_codec_param_t *param, mmsound_codec_info_t *info, MMHandleType *handle)
 {
-       wave_info_t* p = NULL;
+       wave_info_t *h = NULL;
        int ret = 0;
 
 #ifdef DEBUG_DETAIL
        debug_enter();
 #endif
 
-       p = (wave_info_t *) malloc(sizeof(wave_info_t));
-       if (p == NULL) {
+       h = (wave_info_t *)calloc(1, sizeof(wave_info_t));
+       if (h == NULL) {
                debug_error("memory allocation failed");
                return MM_ERROR_OUT_OF_MEMORY;
        }
 
-       memset(p, 0, sizeof(wave_info_t));
-       p->handle = 0;
-       p->repeat_count = param->repeat_count;
-       p->stop_cb = param->stop_cb;
-       p->cb_param = param->param;
-       MMSOUND_STRNCPY(p->filename, param->pfilename, MM_SOUND_MAX_FILENAME);
-       p->client_pid = param->pid;
-       p->stream_index = param->stream_index;
-       MMSOUND_STRNCPY(p->stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
-
-       ret = _sound_prepare(p);
+       h->handle = 0;
+       h->repeat_count = param->repeat_count;
+       h->stop_cb = param->stop_cb;
+       h->cb_param = param->param;
+       MMSOUND_STRNCPY(h->filename, param->pfilename, MM_SOUND_MAX_FILENAME);
+       h->client_pid = param->pid;
+       h->stream_index = param->stream_index;
+       MMSOUND_STRNCPY(h->stream_type, param->stream_type, MAX_STREAM_TYPE_LEN);
+
+       ret = _sound_prepare(h);
        if (ret < 0) {
                debug_error("failed to prepare sound");
                goto error;
        }
 
-       ret = _pa_context_connect(p);
+       ret = _pa_context_connect(h);
        if (ret < 0) {
                debug_error("failed to connect context...");
                goto error;
        }
 
-       ret = _pa_stream_connect(p);
+       ret = _pa_stream_connect(h);
        if (ret < 0) {
                debug_error("failed to connect stream...");
                goto error;
        }
 
-       *handle = (MMHandleType)p;
+       *handle = (MMHandleType)h;
 
 #ifdef DEBUG_DETAIL
-       debug_leave("%p", p);
+       debug_leave("%p", h);
 #endif
        return MM_ERROR_NONE;
 
 error:
-       _sound_unprepare(p);
-       free(p);
+       _sound_unprepare(h);
+       free(h);
        return MM_ERROR_SOUND_INTERNAL;
 }
 
 
 static int _mm_sound_plug_codec_wave_play(MMHandleType handle)
 {
-       wave_info_t *p = (wave_info_t *) handle;
+       wave_info_t *h = (wave_info_t *)handle;
 
-       debug_msg("Start handle %p", p);
-       _pa_stream_uncork(p);
+       debug_msg("Start handle(%p), stream(%p), written(%zu)", h, h->s, h->written);
+       _pa_stream_uncork(h);
 
        return MM_ERROR_NONE;
 }
 
 static int _mm_sound_plug_codec_wave_stop(MMHandleType handle)
 {
-       wave_info_t *p = (wave_info_t*) handle;
-
-       if (!p) {
+       wave_info_t *h = (wave_info_t *)handle;
+       if (!h) {
                debug_error("The handle is null");
                return MM_ERROR_SOUND_INTERNAL;
        }
 
-       debug_msg("Handle %p stop requested", p);
+       debug_msg("Handle %p stop requested", h);
 
-       _pa_stream_stop_disconnect(p);
+       _pa_stream_stop_disconnect(h);
 
-       if (p->stop_cb)
-               p->stop_cb(p->cb_param);
+       if (h->stop_cb)
+               h->stop_cb(h->cb_param, true);
 
        return MM_ERROR_NONE;
 }
 
 static int _mm_sound_plug_codec_wave_destroy(MMHandleType handle)
 {
-       wave_info_t *p = (wave_info_t *)handle;
+       wave_info_t *h = (wave_info_t *)handle;
 
-       if (!p) {
+       if (!h) {
                debug_error("Can not destroy handle :: handle is invalid");
                return MM_ERROR_SOUND_INVALID_POINTER;
        }
 
-       _sound_unprepare(p);
+       _sound_unprepare(h);
 
-       free(p);
-       p = NULL;
+       free(h);
+       h = NULL;
 
        return MM_ERROR_NONE;
 }