From: Jimmy Huang Date: Thu, 6 Mar 2014 23:10:41 +0000 (-0800) Subject: Implements TIVI-1126 - Support ringtone for incoming call X-Git-Tag: accepted/tizen/ivi/20140307.001130~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e975a8c8474dfa68f680157fdac42a7f8be75ffb;p=profile%2Fivi%2Flemolo.git Implements TIVI-1126 - Support ringtone for incoming call - Add support for ringtone playback through pulseaudio - Added sample ringtone using gettext-generated human voice Change-Id: I9fc9e19e73bd2764fcad762efa2e55d606c379db Signed-off-by: Jimmy Huang --- diff --git a/Makefile.am b/Makefile.am index cd5a83b..7f29e81 100644 --- a/Makefile.am +++ b/Makefile.am @@ -170,6 +170,9 @@ if HAVE_TIZEN EDJE_FLAGS += -DHAVE_TIZEN=1 endif +ringtonesdir = $(pkgdatadir)/ringtones +ringtones_DATA = data/ringtones/default.wav + filesdir = $(pkgdatadir)/themes files_DATA = \ data/themes/default.edj \ diff --git a/configure.ac b/configure.ac index 86a7179..3f85ae8 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,7 @@ PKG_CHECK_MODULES([PULSEAUDIO], [ libpulse libpulse-mainloop-glib + libpulse-simple ]) EFL_WITH_BIN([edje], [edje-cc], [edje_cc]) diff --git a/data/ringtones/default.wav b/data/ringtones/default.wav new file mode 100644 index 0000000..2839ae8 Binary files /dev/null and b/data/ringtones/default.wav differ diff --git a/dialer/callscreen.c b/dialer/callscreen.c index 42ab020..a4d8a38 100644 --- a/dialer/callscreen.c +++ b/dialer/callscreen.c @@ -11,6 +11,7 @@ #include "ofono.h" #include "util.h" #include "simple-popup.h" +#include "pulseaudio.h" #include "i18n.h" typedef struct _Callscreen @@ -1004,8 +1005,10 @@ static void _call_added(void *data, OFono_Call *c) _call_waiting_set(ctx, c); else { _call_auto_place(ctx, c); - if (state == OFONO_CALL_STATE_INCOMING) + if (state == OFONO_CALL_STATE_INCOMING) { + pa_play_ringtone(); _call_incoming_set(ctx, c); + } } gui_call_enter(); @@ -1018,6 +1021,7 @@ static void _call_removed(void *data, OFono_Call *c) ctx, ctx->calls.first, ctx->calls.second, ctx->calls.current, ctx->calls.waiting, c); + pa_stop_ringtone(); ctx->calls.list = eina_list_remove(ctx->calls.list, c); _call_disconnected_show(ctx, c, "local"); } @@ -1235,9 +1239,13 @@ static void _call_changed(void *data, OFono_Call *c) Callscreen *ctx = data; OFono_Call_State state = ofono_call_state_get(c); - DBG("BEGIN: ctx=%p, %p, %p, current=%p, waiting=%p, changed=%p (%d)", + DBG("BEGIN: ctx=%p, %p, %p, current=%p, waiting=%p, changed=%p (%s)", ctx, ctx->calls.first, ctx->calls.second, ctx->calls.current, - ctx->calls.waiting, c, state); + ctx->calls.waiting, c, _call_state_str(state)); + + if (state == OFONO_CALL_STATE_ACTIVE || state == OFONO_CALL_STATE_DISCONNECTED) { + pa_stop_ringtone(); + } if (ctx->calls.waiting == c) _call_changed_waiting_update(ctx, c); @@ -1267,9 +1275,9 @@ static void _call_changed(void *data, OFono_Call *c) _call_changed_swap_merge_update(ctx); - DBG("END: ctx=%p, %p, %p, current=%p, waiting=%p, changed=%p (%d)", + DBG("END: ctx=%p, %p, %p, current=%p, waiting=%p, changed=%p (%s)", ctx, ctx->calls.first, ctx->calls.second, ctx->calls.current, - ctx->calls.waiting, c, state); + ctx->calls.waiting, c, _call_state_str(state)); } static void _call_disconnected(void *data, OFono_Call *c, const char *reason) diff --git a/packaging/lemolo.spec b/packaging/lemolo.spec index 3e71da1..df3c1d3 100644 --- a/packaging/lemolo.spec +++ b/packaging/lemolo.spec @@ -55,6 +55,7 @@ rm -rf %{buildroot} %{_bindir}/dialer_open %{_bindir}/message_daemon %{_datadir}/lemolo/examples/contacts.csv +%{_datadir}/lemolo/ringtones/default.wav %{_datadir}/lemolo/scripts/ofono-efl-contacts-db-create.py %{_datadir}/lemolo/themes/default.edj %{_datadir}/lemolo/themes/night.edj diff --git a/utils/pulseaudio.c b/utils/pulseaudio.c index 294d1e5..f63d09b 100644 --- a/utils/pulseaudio.c +++ b/utils/pulseaudio.c @@ -5,15 +5,110 @@ #include #include #include +#include +#include "fcntl.h" #include "pulseaudio.h" #include "log.h" +#define BUFFERSIZE 1024 + static pa_glib_mainloop *mainloop = NULL; static pa_context *pa_ctx = NULL; +static pa_simple *connection = NULL; +static Ecore_Thread *ringtone_thread = NULL; +static pa_proplist *proplist = NULL; +static Eina_Bool stopped = EINA_TRUE; + +/* The Sample format to use */ +static const pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = 44100, + .channels = 2 +}; + +static void _play(void *data __UNUSED__, Ecore_Thread *thread) +{ + int error, fd; + char file_path[PATH_MAX]; + + DBG("Ringtone playing"); + stopped = EINA_FALSE; + + snprintf(file_path, sizeof(file_path), "%s/ringtones/default.wav", elm_app_data_dir_get()); + + if ((fd = open(file_path, O_RDONLY)) < 0) { + DBG("open() failed: %s", strerror(errno)); + return; + } + + if (dup2(fd, STDIN_FILENO) < 0 ) { + DBG("dup2() failed: %s", strerror(errno)); + return; + } + + close(fd); + + /* loops until stopped thread is canceled */ + for (;;) { + uint8_t buf[BUFFERSIZE]; + ssize_t r; + + /* check if playing is stopped */ + if (ecore_thread_check(thread)) { + DBG("Ringtone stopping"); + if (pa_simple_flush(connection, &error) < 0) { + ERR("pa_simple_flush() failed: %s\n", pa_strerror(error)); + return; + } + + break; + } + + /* Read the ringtone file */ + if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) { + if (r == 0) { + /* EOF, repeat */ + DBG("Ringtone repeating"); + lseek(STDIN_FILENO, 0, SEEK_SET); + continue; + } + + ERR("reading from ringtone wav file failed"); + return; + } + + /* play iit */ + if (pa_simple_write(connection, buf, (size_t) r, &error) < 0) { + ERR("pa_simple_write() failed: %s", pa_strerror(error)); + return; + } + } + + if (pa_simple_drain(connection, &error) < 0) { + ERR("pa_simple_drain() failed: %s\n", pa_strerror(error)); + } +} + +static void _end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__) +{ + DBG("Ringtone ended"); + if (ringtone_thread) + ringtone_thread = NULL; +} + + +static void _cancel(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__) +{ + DBG("Ringtone stopped"); + if (ringtone_thread) + ringtone_thread = NULL; +} Eina_Bool pa_init(void) { + int error; + if (!mainloop) mainloop = pa_glib_mainloop_new(NULL); @@ -26,16 +121,73 @@ Eina_Bool pa_init(void) PA_CONTEXT_NOFAIL, NULL) < 0) { ERR("Failed to connect to pulseaudio daemon"); - pa_glib_mainloop_free(mainloop); - mainloop = NULL; - return EINA_FALSE; + goto error; } + // Creates a connection for ringtone +#ifdef HAVE_TIZEN + proplist = pa_proplist_new(); + if (pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "phone") < 0) { + DBG("pa_proplist_sets() failed: %s", pa_strerror(error)); + goto error; + } + + if (!(connection = pa_simple_new_proplist(NULL, NULL, PA_STREAM_PLAYBACK, NULL, + "lemolo", &ss, NULL, NULL, proplist, &error))) { + DBG("pa_simple_new() failed: %s", pa_strerror(error)); + goto error; + } +#else + if (!(connection = pa_simple_new(NULL, NULL, PA_STREAM_PLAYBACK, NULL, + "lemolo", &ss, NULL, NULL, &error))) { + DBG("pa_simple_new() failed: %s", pa_strerror(error)); + goto error; + } +#endif + return EINA_TRUE; + +error: + if (connection) + pa_simple_free(connection); + + if (pa_ctx) { + pa_context_disconnect(pa_ctx); + pa_context_unref(pa_ctx); + } + + if (mainloop) { + pa_glib_mainloop_free(mainloop); + mainloop = NULL; + } + + if (proplist) + pa_proplist_free(proplist); + + return EINA_FALSE; +} + +Eina_Bool pa_play_ringtone(void) +{ + if (!ringtone_thread) + ringtone_thread = ecore_thread_run(_play, _end, _cancel, NULL); + + return EINA_TRUE; +} + +void pa_stop_ringtone(void) +{ + if (ringtone_thread) + ecore_thread_cancel(ringtone_thread); } void pa_shutdown(void) { + pa_stop_ringtone(); + + if (connection) + pa_simple_free(connection); + if (pa_ctx) { pa_context_disconnect(pa_ctx); pa_context_unref(pa_ctx); @@ -45,4 +197,7 @@ void pa_shutdown(void) pa_glib_mainloop_free(mainloop); mainloop = NULL; } + + if (proplist) + pa_proplist_free(proplist); } diff --git a/utils/pulseaudio.h b/utils/pulseaudio.h index 5dca36b..925f11f 100644 --- a/utils/pulseaudio.h +++ b/utils/pulseaudio.h @@ -3,6 +3,10 @@ Eina_Bool pa_init(void); +Eina_Bool pa_play_ringtone(void); + +void pa_stop_ringtone(void); + void pa_shutdown(void); #endif