53a4beab24132cf8ba6670c8259ddade0d351838
[src/app-framework-binder.git] / plugins / audio / audio-api.c
1 /*
2  * Copyright (C) 2015 "IoT.bzh"
3  * Author "Manuel Bachmann"
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include "audio-api.h"
20 #include "audio-alsa.h"
21
22
23 /* ------ LOCAL HELPER FUNCTIONS --------- */
24
25 /* private client context creation ; default values */
26 STATIC audioCtxHandleT* initAudioCtx () {
27
28     audioCtxHandleT *ctx;
29
30     ctx = malloc (sizeof(audioCtxHandleT));
31     ctx->idx = -1;
32     ctx->volume = 25;
33     ctx->channels = 2;
34     ctx->mute = 0;
35     ctx->is_playing = 0;
36
37     return ctx;
38 }
39
40 STATIC AFB_error releaseAudio (audioCtxHandleT *ctx) {
41
42     /* power it off */
43     _alsa_free (ctx->idx);
44
45     /* clean client context */
46     ctx->idx = -1;
47
48     return AFB_SUCCESS;
49 }
50
51 /* called when client session dies [e.g. client quits for more than 15mns] */
52 STATIC json_object* freeAudio (AFB_clientCtx *client) {
53
54     releaseAudio (client->ctx);
55     free (client->ctx);
56     
57     return jsonNewMessage (AFB_SUCCESS, "Released radio and client context");
58 }
59
60
61 /* ------ PUBLIC PLUGIN FUNCTIONS --------- */
62
63 STATIC json_object* init (AFB_request *request) {       /* AFB_SESSION_CREATE */
64
65     audioCtxHandleT *ctx;
66     json_object *jresp;
67     int idx;
68
69     /* create a private client context */
70     ctx = initAudioCtx();
71     request->client->ctx = (audioCtxHandleT*)ctx;
72     
73     _alsa_init("default", ctx);
74     
75     jresp = json_object_new_object();
76     json_object_object_add (jresp, "token", json_object_new_string (request->client->token));
77     return jresp;
78 }
79
80 STATIC json_object* volume (AFB_request *request) {      /* AFB_SESSION_CHECK */
81
82     audioCtxHandleT *ctx = (audioCtxHandleT*)request->client->ctx;
83     const char *value = getQueryValue (request, "value");
84     json_object *jresp;
85     int volume;
86     char volume_str[256];
87
88     /* no "?value=" parameter : return current state */
89     if (!value) {
90         ctx->volume = _alsa_get_volume (ctx->idx);
91         snprintf (volume_str, sizeof(volume_str), "%d", ctx->volume);
92         jresp = json_object_new_object();
93         json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
94     }
95
96     /* "?value=" parameter, set volume */
97     else {
98         volume = atoi (value);
99         if (100 < volume < 0) {
100             request->errcode = MHD_HTTP_SERVICE_UNAVAILABLE;
101             return (jsonNewMessage (AFB_FAIL, "Volume must be between 0 and 100"));
102         }
103         ctx->volume = volume;
104         _alsa_set_volume (ctx->idx, ctx->volume);
105
106         snprintf (volume_str, sizeof(volume_str), "%d", ctx->volume);
107         jresp = json_object_new_object();
108         json_object_object_add (jresp, "volume", json_object_new_string(volume_str));
109     }
110
111     return jresp;
112 }
113
114 STATIC json_object* channels (AFB_request *request) {    /* AFB_SESSION_CHECK */
115
116     audioCtxHandleT *ctx = (audioCtxHandleT*)request->client->ctx;
117     const char *value = getQueryValue (request, "value");
118     json_object *jresp = json_object_new_object();
119     char channels_str[256];
120
121     /* no "?value=" parameter : return current state */
122     if (!value) {
123         snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
124         json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
125     }
126
127     /* "?value=" parameter, set channels */
128     else {
129         ctx->channels = atoi (value);
130         _alsa_set_channels (ctx->idx, ctx->channels);
131
132         snprintf (channels_str, sizeof(channels_str), "%d", ctx->channels);
133         json_object_object_add (jresp, "channels", json_object_new_string (channels_str));
134     }
135
136     return jresp;
137 }
138
139 STATIC json_object* mute (AFB_request *request) {        /* AFB_SESSION_CHECK */
140
141     audioCtxHandleT *ctx = (audioCtxHandleT*)request->client->ctx;
142     const char *value = getQueryValue (request, "value");
143     json_object *jresp = json_object_new_object();
144
145     /* no "?value=" parameter : return current state */
146     if (!value) {
147         ctx->mute = _alsa_get_mute (ctx->idx);
148         ctx->mute ?
149             json_object_object_add (jresp, "mute", json_object_new_string ("on"))
150           : json_object_object_add (jresp, "mute", json_object_new_string ("off"));
151     }
152
153     /* "?value=" parameter is "1" or "true" */
154     else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
155         ctx->mute = 1;
156         _alsa_set_mute (ctx->idx, ctx->mute);
157
158         json_object_object_add (jresp, "mute", json_object_new_string ("on"));
159     }
160
161     /* "?value=" parameter is "0" or "false" */
162     else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
163         ctx->mute = 0;
164         _alsa_set_mute (ctx->idx, ctx->mute);
165
166         json_object_object_add (jresp, "mute", json_object_new_string ("off"));
167     }
168
169     return jresp;
170 }
171
172 STATIC json_object* play (AFB_request *request) {        /* AFB_SESSION_CHECK */
173
174     audioCtxHandleT *ctx = (audioCtxHandleT*)request->client->ctx;
175     const char *value = getQueryValue (request, "value");
176     json_object *jresp = json_object_new_object();
177
178     /* no "?value=" parameter : return current state */
179     if (!value) {
180         ctx->is_playing ?
181             json_object_object_add (jresp, "play", json_object_new_string ("on"))
182           : json_object_object_add (jresp, "play", json_object_new_string ("off"));
183     }
184
185     /* "?value=" parameter is "1" or "true" */
186     else if ( atoi(value) == 1 || !strcasecmp(value, "true") ) {
187         ctx->is_playing = 1;
188         _alsa_play (ctx->idx);
189
190         json_object_object_add (jresp, "play", json_object_new_string ("on"));
191     }
192
193     /* "?value=" parameter is "0" or "false" */
194     else if ( atoi(value) == 0 || !strcasecmp(value, "false") ) {
195         ctx->is_playing = 0;
196         _alsa_stop (ctx->idx);
197
198         json_object_object_add (jresp, "play", json_object_new_string ("off"));
199     }
200
201     return jresp;
202 }
203
204 STATIC json_object* refresh (AFB_request *request) {     /* AFB_SESSION_RENEW */
205     json_object *jresp = json_object_new_object();
206     json_object_object_add(jresp, "token", json_object_new_string (request->client->token));
207     return jresp;
208 }
209
210 STATIC json_object* ping (AFB_request *request) {         /* AFB_SESSION_NONE */
211     return jsonNewMessage(AFB_SUCCESS, "Ping Binder Daemon - Radio API");
212 }
213
214
215 STATIC AFB_restapi pluginApis[]= {
216   {"init"    , AFB_SESSION_CREATE, (AFB_apiCB)init      , "Audio API - init"},
217   {"volume"  , AFB_SESSION_CHECK,  (AFB_apiCB)volume    , "Audio API - volume"},
218   {"channels", AFB_SESSION_CHECK,  (AFB_apiCB)channels  , "Audio API - channels"},
219   {"mute"    , AFB_SESSION_CHECK,  (AFB_apiCB)mute      , "Audio API - mute"},
220   {"play"    , AFB_SESSION_CHECK,  (AFB_apiCB)play      , "Audio API - play"},
221   {"refresh" , AFB_SESSION_RENEW,  (AFB_apiCB)refresh   , "Audio API - refresh"},
222   {"ping"    , AFB_SESSION_NONE,   (AFB_apiCB)ping      , "Audio API - ping"},
223   {NULL}
224 };
225
226 PUBLIC AFB_plugin *audioRegister () {
227     AFB_plugin *plugin = malloc (sizeof(AFB_plugin));
228     plugin->type   = AFB_PLUGIN_JSON;
229     plugin->info   = "Application Framework Binder - Audio plugin";
230     plugin->prefix = "audio";        
231     plugin->apis   = pluginApis;
232
233     plugin->freeCtxCB = freeAudio;
234
235     return (plugin);
236 };