2 * Remix Stream Player: TIZEN device output
4 * Govindaraju SM <govi.sm@samsung.com>, August 2011
5 * Prince Kumar Dubey <prince.dubey@samsung.com>, August 2011
13 #include <remix/remix.h>
15 #ifdef HAVE_LIBSNDFILE
20 int _edje_multisense_default_log_dom = -1;
25 #define ERR(...) EINA_LOG_DOM_ERR(_edje_multisense_default_log_dom, __VA_ARGS__)
29 #define WRN(...) EINA_LOG_DOM_WARN(_edje_multisense_default_log_dom, __VA_ARGS__)
31 #define STREAM_PLAYER_BUFFERLEN 2048
32 #define DEFAULT_FORMAT MMSOUND_PCM_S16_LE
34 typedef struct _RemixPlayerData RemixPlayerData;
35 typedef short PLAYER_PCM;
37 struct _RemixPlayerData {
38 RemixPCM databuffer[STREAM_PLAYER_BUFFERLEN];
39 PLAYER_PCM *playbuffer;
40 MMSoundPcmHandle_t handle;
41 MMSoundPcmChannel_t channel;
46 unsigned int buffer_size;
51 /* Optimisation dependencies: none */
52 static RemixBase *remix_player_optimise (RemixEnv *env, RemixBase *base);
55 remix_player_reset_device (RemixEnv *env, RemixBase *base)
58 RemixPlayerData *player_data = remix_base_get_instance_data(env, base);
60 if (player_data->handle)
62 mm_sound_pcm_play_close(player_data->handle);
63 player_data->handle = NULL;
65 old_buffer_size = player_data->buffer_size;
66 player_data->buffer_size = mm_sound_pcm_play_open(&player_data->handle,
67 player_data->frequency,
71 if(player_data->buffer_size < 0)
73 remix_set_error (env, REMIX_ERROR_SYSTEM);
77 if( old_buffer_size < player_data->buffer_size)
79 if( player_data->playbuffer ) free(player_data->playbuffer);
80 player_data->playbuffer = calloc(sizeof(PLAYER_PCM), player_data->buffer_size);
81 if(!player_data->playbuffer)
83 remix_set_error (env, REMIX_ERROR_SYSTEM);
91 _vconf_noti_key_changed_cb(keynode_t *node, void *data)
93 RemixPlayerData *player = (RemixPlayerData *)data;
94 char *keyname = vconf_keynode_get_name(node);
96 if (strcmp(keyname, VCONFKEY_SETAPPL_SOUND_STATUS_BOOL) == 0)
97 player->snd_on = vconf_keynode_get_bool(node);
99 else if (strcmp(keyname, VCONFKEY_SYSMAN_EARJACK) == 0)
101 int ear_jack = vconf_keynode_get_int(node);
102 if (ear_jack == VCONFKEY_SYSMAN_EARJACK_REMOVED)
103 remix_player_reset_device (player->env, player->base);
108 remix_player_init (RemixEnv *env, RemixBase *base, CDSet *parameters)
110 RemixCount nr_channels;
112 RemixPlayerData *player_data = calloc(1, sizeof (RemixPlayerData));
116 remix_set_error(env, REMIX_ERROR_SYSTEM);
120 remix_base_set_instance_data(env, base, player_data);
121 channels = remix_get_channels (env);
123 nr_channels = cd_set_size (env, channels);
124 if (nr_channels == 1)
126 player_data->stereo = 0;
127 player_data->channel = MMSOUND_PCM_MONO;
129 else if (nr_channels == 2)
131 player_data->stereo = 1;
132 player_data->channel = MMSOUND_PCM_STEREO;
135 player_data->frequency = remix_get_samplerate(env);
136 player_data->buffer_size = 0;
137 player_data->max_value = (RemixPCM) SHRT_MAX / 2;
139 remix_player_reset_device (env, (RemixBase *)base);
141 base = remix_player_optimise (env, base);
142 player_data->env = env;
143 player_data->base = base;
144 if (vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &player_data->snd_on) < 0)
145 WRN("\nFail to get VCONFKEY_SETAPPL_SOUND_STATUS_BOOL boolean value");
147 if (vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL,_vconf_noti_key_changed_cb, player_data) < 0)
148 WRN("\nFail to register VCONFKEY_SETAPPL_SOUND_STATUS_BOOL key callback");
149 if (vconf_notify_key_changed(VCONFKEY_SYSMAN_EARJACK, _vconf_noti_key_changed_cb, player_data) < 0)
150 WRN("\nFail to register VCONFKEY_SYSMAN_EARJACK key callback");
157 remix_player_clone (RemixEnv *env, RemixBase *base)
159 RemixBase *new_player = remix_base_new (env);
161 remix_player_init( env, new_player, NULL);
166 remix_player_destroy (RemixEnv *env, RemixBase *base)
168 RemixPlayerData *player_data = remix_base_get_instance_data(env, base);
170 if (vconf_ignore_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL,_vconf_noti_key_changed_cb) < 0)
171 WRN("\nFail to unregister VCONFKEY_SETAPPL_SOUND_STATUS_BOOL key callback");
172 if (vconf_ignore_key_changed(VCONFKEY_SYSMAN_EARJACK, _vconf_noti_key_changed_cb) < 0)
173 WRN("\nFail to unregister VCONFKEY_SYSMAN_EARJACK key callback");
175 if(player_data->handle)
176 mm_sound_pcm_play_close(player_data->handle);
177 if(player_data->playbuffer) free(player_data->playbuffer);
183 remix_player_ready (RemixEnv *env, RemixBase *base)
185 RemixPlayerData *player_data = remix_base_get_instance_data(env, base);
186 RemixCount nr_channels;
190 channels = remix_get_channels (env);
191 samplerate = (int) remix_get_samplerate (env);
193 nr_channels = cd_set_size (env, channels);
195 return (samplerate == player_data->frequency &&
196 ((nr_channels == 1 && player_data->stereo == 0) ||
197 (nr_channels > 1 && player_data->stereo == 1)));
201 remix_player_prepare (RemixEnv *env, RemixBase *base)
203 remix_player_reset_device (env, base);
208 remix_player_playbuffer (RemixEnv *env, RemixPlayerData *player, RemixPCM *data,
216 length = count * sizeof(RemixCount);
218 for (i = 0; i < count; i++)
220 value = *data++ * (player->max_value);
221 *(player->playbuffer + i) = (PLAYER_PCM) value;
224 ret = mm_sound_pcm_play_write(player->handle,
233 /* An RemixChunkFunc for making noise */
235 remix_player_chunk (RemixEnv *env, RemixChunk *chunk, RemixCount offset,
236 RemixCount count, int channelname, void *data)
238 RemixPlayerData *player = (RemixPlayerData *)data;
239 RemixCount remaining = count, written = 0, n, playcount;
242 while (remaining > 0)
244 playcount = MIN (remaining, player->buffer_size);
246 d = &chunk->data[offset];
247 n = remix_player_playbuffer (env, player, d, playcount);
252 n /= sizeof (PLAYER_PCM);
263 remix_player_process (RemixEnv *env, RemixBase *base, RemixCount count,
264 RemixStream *input, RemixStream *output)
266 RemixCount remaining = count, processed = 0, n, nn, nr_channels;
267 RemixPlayerData *player_data = remix_base_get_instance_data(env, base);
269 if (!player_data->snd_on) return count;
270 nr_channels = remix_stream_nr_channels (env, input);
272 if (nr_channels == 1 && player_data->stereo == 0)
274 return remix_stream_chunkfuncify (env, input, count,
275 remix_player_chunk, player_data);
277 else if (nr_channels == 2 && player_data->stereo == 1)
279 while (remaining > 0)
281 n = MIN (remaining, (player_data->buffer_size / 2) );
282 n = remix_stream_interleave_2 (env, input,
283 REMIX_CHANNEL_LEFT, REMIX_CHANNEL_RIGHT,
284 player_data->databuffer, n);
286 nn = remix_player_playbuffer (env, player_data,
287 player_data->databuffer, nn);
296 ERR("[remix_player_process] unsupported stream/output channel\n");
297 ERR ("combination %ld / %d\n", nr_channels, player_data->stereo ? 2 : 1);
303 remix_player_length (RemixEnv *env, RemixBase *base)
305 return REMIX_COUNT_INFINITE;
309 remix_player_seek (RemixEnv *env, RemixBase *base, RemixCount count)
315 remix_player_flush (RemixEnv *env, RemixBase *base)
317 RemixPlayerData *player_data = remix_base_get_instance_data(env, base);
318 remix_player_reset_device (env, base);
322 static struct _RemixMethods _remix_player_methods = {
324 remix_player_destroy,
326 remix_player_prepare,
327 remix_player_process,
334 remix_player_optimise (RemixEnv *env, RemixBase *base)
336 remix_base_set_methods (env, base, &_remix_player_methods);
340 static struct _RemixMetaText tizen_player_metatext = {
342 "TIZEN Sound Player",
343 "Output the stream into TIZEN System",
344 "Copyright (C) 2011, Samsung Electronics Co., Ltd.",
345 "http://www.samsung.com",
346 REMIX_ONE_AUTHOR ("govi.sm@samsung.com", "prince.dubey@samsung.com"),
349 static struct _RemixPlugin tizen_player_plugin = {
350 &tizen_player_metatext,
352 CD_EMPTY_SET, /* init scheme */
354 CD_EMPTY_SET, /* process scheme */
356 NULL, /* plugin data */
361 remix_load (RemixEnv *env)
363 CDList *plugins = cd_list_new (env);
364 plugins = cd_list_prepend (env, plugins,
365 CD_POINTER(&tizen_player_plugin));