Fixes TC-2116 - Use uninitialized values
[profile/ivi/lemolo.git] / utils / pulseaudio.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
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>
9
10 #include "fcntl.h"
11 #include "pulseaudio.h"
12 #include "log.h"
13
14 #define BUFFERSIZE 1024
15
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;
22
23 /* The Sample format to use */
24 static const pa_sample_spec ss = {
25         .format = PA_SAMPLE_S16LE,
26         .rate = 44100,
27         .channels = 2
28 };
29
30 static void _play(void *data __UNUSED__, Ecore_Thread *thread)
31 {
32         int error, fd;
33         char file_path[PATH_MAX];
34
35         DBG("Ringtone playing");
36         stopped = EINA_FALSE;
37
38         snprintf(file_path, sizeof(file_path), "%s/ringtones/default.wav", elm_app_data_dir_get());
39
40         if ((fd = open(file_path, O_RDONLY)) < 0) {
41                 DBG("open() failed: %s", strerror(errno));
42                 return;
43         }
44
45         if (dup2(fd, STDIN_FILENO) < 0 ) {
46                 DBG("dup2() failed: %s", strerror(errno));
47                 return;
48         }
49
50         close(fd);
51
52         /* loops until stopped thread is canceled */
53         for (;;) {
54                 uint8_t buf[BUFFERSIZE];
55                 ssize_t r;
56
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));
62                                 return;
63                         }
64
65                         break;
66                 }
67
68                 /* Read the ringtone file */
69                 if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) {
70                         if (r == 0) {
71                                 /* EOF, repeat */
72                                 DBG("Ringtone repeating");
73                                 lseek(STDIN_FILENO, 0, SEEK_SET);
74                                 continue;
75                         }
76
77                         ERR("reading from ringtone wav file failed");
78                         return;
79                 }
80
81                 /* play iit */
82                 if (pa_simple_write(connection, buf, (size_t) r, &error) < 0) {
83                         ERR("pa_simple_write() failed: %s", pa_strerror(error));
84                         return;
85                 }
86         }
87
88         if (pa_simple_drain(connection, &error) < 0) {
89                 ERR("pa_simple_drain() failed: %s\n", pa_strerror(error));
90         }
91 }
92
93 static void _end(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
94 {
95         DBG("Ringtone ended");
96         if (ringtone_thread)
97                 ringtone_thread = NULL;
98 }
99
100
101 static void _cancel(void *data __UNUSED__, Ecore_Thread *thread __UNUSED__)
102 {
103         DBG("Ringtone stopped");
104         if (ringtone_thread)
105                 ringtone_thread = NULL;
106 }
107
108 Eina_Bool pa_init(void)
109 {
110         int error;
111
112         if (!mainloop)
113                 mainloop = pa_glib_mainloop_new(NULL);
114
115         pa_ctx = pa_context_new(pa_glib_mainloop_get_api(mainloop),
116                                  "lemolo");
117
118         // connects to the pulse server
119         error = pa_context_connect(pa_ctx, NULL, PA_CONTEXT_NOFAIL, NULL);
120         if (error < 0)
121         {
122                 ERR("Failed to connect to pulseaudio daemon: %s", pa_strerror(error));
123                 goto error;
124         }
125
126         // Creates a connection for ringtone
127 #ifdef HAVE_TIZEN
128         proplist = pa_proplist_new();
129         error = pa_proplist_sets(proplist, PA_PROP_MEDIA_ROLE, "phone");
130         if (error < 0) {
131                 DBG("pa_proplist_sets() failed: %s", pa_strerror(error));
132                 goto error;
133         }
134
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));
138                 goto error;
139         }
140 #else
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));
144                 goto error;
145         }
146 #endif
147
148         return EINA_TRUE;
149
150 error:
151         if (connection)
152                 pa_simple_free(connection);
153
154         if (pa_ctx) {
155                 pa_context_disconnect(pa_ctx);
156                 pa_context_unref(pa_ctx);
157         }
158
159         if (mainloop) {
160                 pa_glib_mainloop_free(mainloop);
161                 mainloop = NULL;
162         }
163
164         if (proplist)
165                 pa_proplist_free(proplist);
166
167         return EINA_FALSE;
168 }
169
170 Eina_Bool pa_play_ringtone(void)
171 {
172         if (!ringtone_thread)
173                 ringtone_thread = ecore_thread_run(_play, _end, _cancel, NULL);
174
175         return EINA_TRUE;
176 }
177
178 void pa_stop_ringtone(void)
179 {
180         if (ringtone_thread)
181                 ecore_thread_cancel(ringtone_thread);
182 }
183
184 void pa_shutdown(void)
185 {
186         pa_stop_ringtone();
187
188         if (connection)
189                 pa_simple_free(connection);
190
191         if (pa_ctx) {
192                 pa_context_disconnect(pa_ctx);
193                 pa_context_unref(pa_ctx);
194         }
195
196         if (mainloop) {
197                 pa_glib_mainloop_free(mainloop);
198                 mainloop = NULL;
199         }
200
201         if (proplist)
202                 pa_proplist_free(proplist);
203 }