4 #include <Elementary.h>
5 #include <pulse/context.h>
6 #include <pulse/pulseaudio.h>
7 #include <pulse/glib-mainloop.h>
8 #include <pulse/simple.h>
11 #include "pulseaudio.h"
14 #define BUFFERSIZE 1024
16 static pa_glib_mainloop *mainloop = NULL;
17 static pa_context *pa_ctx = NULL;
18 static pa_simple *connection = NULL;
19 static Ecore_Thread *ringtone_thread = NULL;
20 static pa_proplist *proplist = NULL;
21 static Eina_Bool stopped = EINA_TRUE;
23 /* The Sample format to use */
24 static const pa_sample_spec ss = {
25 .format = PA_SAMPLE_S16LE,
30 static void _play(void *data __UNUSED__, Ecore_Thread *thread)
33 char file_path[PATH_MAX];
35 DBG("Ringtone playing");
38 snprintf(file_path, sizeof(file_path), "%s/ringtones/default.wav", elm_app_data_dir_get());
40 if ((fd = open(file_path, O_RDONLY)) < 0) {
41 DBG("open() failed: %s", strerror(errno));
45 if (dup2(fd, STDIN_FILENO) < 0 ) {
46 DBG("dup2() failed: %s", strerror(errno));
52 /* loops until stopped thread is canceled */
54 uint8_t buf[BUFFERSIZE];
57 /* check if playing is stopped */
58 if (ecore_thread_check(thread)) {
59 DBG("Ringtone stopping");
60 if (pa_simple_flush(connection, &error) < 0) {
61 ERR("pa_simple_flush() failed: %s\n", pa_strerror(error));
68 /* Read the ringtone file */
69 if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) {
72 DBG("Ringtone repeating");
73 lseek(STDIN_FILENO, 0, SEEK_SET);
77 ERR("reading from ringtone wav file failed");
82 if (pa_simple_write(connection, buf, (size_t) r, &error) < 0) {
83 ERR("pa_simple_write() failed: %s", pa_strerror(error));
88 if (pa_simple_drain(connection, &error) < 0) {
89 ERR("pa_simple_drain() failed: %s\n", pa_strerror(error));
93 static void _end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
95 DBG("Ringtone ended");
97 ringtone_thread = NULL;
101 static void _cancel(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
103 DBG("Ringtone stopped");
105 ringtone_thread = NULL;
108 Eina_Bool pa_init(void)
113 mainloop = pa_glib_mainloop_new(NULL);
115 pa_ctx = pa_context_new(pa_glib_mainloop_get_api(mainloop),
118 // connects to the pulse server
119 error = pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFAIL, NULL);
122 ERR("Failed to connect to pulseaudio daemon: %s", pa_strerror(error));
126 // Creates a connection for ringtone
128 proplist = pa_proplist_new();
129 error = pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "phone");
131 DBG("pa_proplist_sets() failed: %s", pa_strerror(error));
135 if (!(connection = pa_simple_new_proplist(NULL, NULL, PA_STREAM_PLAYBACK, NULL,
136 "lemolo", &ss, NULL, NULL, proplist, &error))) {
137 DBG("pa_simple_new() failed: %s", pa_strerror(error));
141 if (!(connection = pa_simple_new(NULL, NULL, PA_STREAM_PLAYBACK, NULL,
142 "lemolo", &ss, NULL, NULL, &error))) {
143 DBG("pa_simple_new() failed: %s", pa_strerror(error));
152 pa_simple_free(connection);
155 pa_context_disconnect(pa_ctx);
156 pa_context_unref(pa_ctx);
160 pa_glib_mainloop_free(mainloop);
165 pa_proplist_free(proplist);
170 Eina_Bool pa_play_ringtone(void)
172 if (!ringtone_thread)
173 ringtone_thread = ecore_thread_run(_play, _end, _cancel, NULL);
178 void pa_stop_ringtone(void)
181 ecore_thread_cancel(ringtone_thread);
184 void pa_shutdown(void)
189 pa_simple_free(connection);
192 pa_context_disconnect(pa_ctx);
193 pa_context_unref(pa_ctx);
197 pa_glib_mainloop_free(mainloop);
202 pa_proplist_free(proplist);