mp3splt-gtk

- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

gstreamer_control.c
Go to the documentation of this file.
1 /**********************************************************
2 *
3 * mp3splt-gtk -- utility based on mp3splt,
4 * for mp3/ogg splitting without decoding
5 *
6 * Copyright: (C) 2005-2013 Alexandru Munteanu
7 * Contact: m@ioalex.net
8 *
9 * from BMP to Audacious patch from Roberto Neri - 2007,2008
10 *
11 * http://mp3splt.sourceforge.net/
12 *
13 *********************************************************/
14
15 /**********************************************************
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation; either version 2
20 * of the License, or (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
30 * USA.
31 *
32 *********************************************************/
33
34 /*!*******************************************************
35 * \file
36 * Control the gstreamer framework
37 *
38 * this file has functions to control the 'internal'
39 + gstreamer player
40 *********************************************************/
41
42 #ifndef NO_GSTREAMER
43
44 #include <gst/gst.h>
45
46 #include "gstreamer_control.h"
47
49 static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data)
50 {
51 enter_threads();
52
53 ui_state *ui = (ui_state *) data;
54
55 switch (GST_MESSAGE_TYPE(msg))
56 {
57 case GST_MESSAGE_ERROR:
58 {
59 gchar *debug;
60 GError *error;
61
62 gst_message_parse_error (msg, &error, &debug);
63 g_free(debug);
64
65 gchar *message = NULL;
66 if (error->message != NULL)
67 {
68 gint malloc_size = strlen(error->message) + 20;
69 message = malloc(sizeof(char) * malloc_size);
70 if (message)
71 {
72 memset(message,'\0',malloc_size);
73 g_snprintf(message, malloc_size,_("gstreamer error: %s"),error->message);
74
75 put_status_message(message, ui);
76
77 g_free(message);
78 }
79 }
80 g_error_free(error);
81 break;
82 }
83 case GST_MESSAGE_WARNING:
84 {
85 gchar *debug;
86 GError *error;
87
88 gst_message_parse_warning(msg, &error, &debug);
89 g_free(debug);
90
91 gchar *message = NULL;
92 if (error->message != NULL)
93 {
94 gint malloc_size = strlen(error->message) + 20;
95 message = malloc(sizeof(char) * malloc_size);
96 if (message)
97 {
98 memset(message,'\0',malloc_size);
99 g_snprintf(message, malloc_size,_("Warning: %s"),error->message);
100
101 put_status_message(message, ui);
102
103 g_free(message);
104 }
105 }
106 g_error_free (error);
107 break;
108 }
109 case GST_MESSAGE_INFO:
110 {
111 gchar *debug;
112 GError *error;
113
114 gst_message_parse_info(msg, &error, &debug);
115 g_free(debug);
116
117 gchar *message = NULL;
118 if (error->message != NULL)
119 {
120 gint malloc_size = strlen(error->message) + 20;
121 message = malloc(sizeof(char) * malloc_size);
122 if (message)
123 {
124 memset(message,'\0',malloc_size);
125 g_snprintf(message, malloc_size,_("Info: %s"),error->message);
126
127 put_status_message(message, ui);
128
129 g_free(message);
130 }
131 }
132 g_error_free (error);
133 break;
134 }
135 case GST_MESSAGE_TAG:
136 {
137 GstTagList *tag_list = NULL;
138 gst_message_parse_tag(msg, &tag_list);
139
140 gint number_of_stream = 0;
141 g_object_get(ui->pi->play, "current-audio", &number_of_stream, NULL);
142
143 //artist
144 const GValue *val = gst_tag_list_get_value_index(tag_list, GST_TAG_ARTIST,
145 number_of_stream);
146 if (val != NULL)
147 {
148 ui->pi->song_artist = g_value_get_string(val);
149 }
150
151 //title
152 val = gst_tag_list_get_value_index(tag_list, GST_TAG_TITLE, number_of_stream);
153 if (val != NULL)
154 {
155 ui->pi->song_title = g_value_get_string(val);
156 }
157
158 //rate (bps)
159 val = gst_tag_list_get_value_index(tag_list, GST_TAG_BITRATE, number_of_stream);
160 if (val != NULL)
161 {
162 ui->pi->rate = g_value_get_uint(val);
163 }
164
165 break;
166 }
167 default:
168 break;
169 }
170
171 exit_threads();
172
173 return TRUE;
174 }
175
177 void gstreamer_get_song_infos(gchar *total_infos, ui_state *ui)
178 {
179 if (!ui->pi->play)
180 {
181 return;
182 }
183
184 gint freq = 0;
185 gint nch = 0;
186
187 gint number_of_stream = 0;
188 g_object_get(ui->pi->play, "current-audio", &number_of_stream, NULL);
189
190 //get the stream info
191 GList *streaminfo = NULL;
192 g_object_get(ui->pi->play, "stream-info", &streaminfo, NULL);
193
194 gchar rate_str[32] = { '\0' };
195 gchar freq_str[32] = { '\0' };
196 gchar nch_str[32] = { '\0' };
197
198 gchar *_Kbps = _("Kbps");
199 gchar *_Khz = _("Khz");
200
201 GObject *object = g_list_nth_data(streaminfo, number_of_stream);
202 if (object)
203 {
204 GstObject *obj = NULL;
205 g_object_get(G_OBJECT(object), "object", &obj, NULL);
206
207 //get the caps from the first element
208 GstCaps *caps = NULL;
209 g_object_get(obj, "caps", &caps, NULL);
210 if (caps)
211 {
212 //get the structure from the caps
213 GstStructure *structure = NULL;
214 structure = gst_caps_get_structure(caps, number_of_stream);
215
216 //get the rate and the number of channels from the structure
217 gst_structure_get_int(structure, "rate", &freq);
218 gst_structure_get_int(structure, "channels", &nch);
219
220 gst_caps_unref(caps);
221 }
222
223 g_snprintf(rate_str, 32, "%d", ui->pi->rate / 1000);
224 g_snprintf(freq_str, 32, "%d", freq / 1000);
225
226 if (nch >= 2)
227 {
228 snprintf(nch_str, 32, "%s", _("stereo"));
229 }
230 else
231 {
232 snprintf(nch_str, 32, "%s", _("mono"));
233 }
234 }
235
236 if (ui->pi->rate != 0)
237 {
238 g_snprintf(total_infos,512, "%s %s %s %s %s", rate_str,_Kbps,freq_str, _Khz,nch_str);
239 }
240 else
241 {
242 total_infos[0] = '\0';
243 }
244 }
245
250 gchar *gstreamer_get_filename(ui_state *ui)
251 {
252 gchar *fname = get_input_filename(ui->gui);
253 if (fname == NULL)
254 {
255 return NULL;
256 }
257
258 return strdup(fname);
259 }
260
262 gint gstreamer_get_playlist_number(ui_state *ui)
263 {
264 return 1;
265 }
266
271 gchar *gstreamer_get_title_song(ui_state *ui)
272 {
273 player_infos *pi = ui->pi;
274
275 if (pi->song_artist || pi->song_title)
276 {
277 gint title_size = 20;
278
279 if (pi->song_artist)
280 {
281 title_size += strlen(pi->song_artist);
282 }
283
284 if (pi->song_title)
285 {
286 title_size += strlen(pi->song_title);
287 }
288
289 gchar *title = malloc(sizeof(char) * title_size);
290 memset(title, '\0', title_size);
291
292 if (pi->song_artist && pi->song_title)
293 {
294 g_snprintf(title, title_size, "%s - %s", pi->song_artist, pi->song_title);
295 }
296 else if (pi->song_title && !pi->song_artist)
297 {
298 g_snprintf(title, title_size, "%s", pi->song_title);
299 }
300 else if (pi->song_artist && !pi->song_title)
301 {
302 g_snprintf(title, title_size, "%s", pi->song_artist);
303 }
304
305 return title;
306 }
307
308 gchar *fname = gstreamer_get_filename(ui);
309 if (fname != NULL)
310 {
311 gchar *file = strrchr(fname, G_DIR_SEPARATOR);
312 if (file != NULL)
313 {
314 gchar *alloced_file = strdup(file+1);
315 g_free(fname);
316 fname = NULL;
317 return alloced_file;
318 }
319 else
320 {
321 return fname;
322 }
323 }
324 else
325 {
326 return strdup("-");
327 }
328 }
329
331 gint gstreamer_get_time_elapsed(ui_state *ui)
332 {
333 if (!ui->pi->play)
334 {
335 return 0;
336 }
337
338 GstQuery *query = gst_query_new_position(GST_FORMAT_TIME);
339 gint64 time = 0;
340
341 if (gst_element_query(ui->pi->play, query))
342 {
343 gst_query_parse_position(query, NULL, &time);
344 }
345
346 gst_query_unref(query);
347
348 return (gint) (time / GST_MSECOND);
349 }
350
352 void gstreamer_start(ui_state *ui)
353 {
354 if (ui->pi->play)
355 {
356 gstreamer_quit(ui);
357 gst_object_unref(ui->pi->play);
358 }
359
360 gst_init(NULL, NULL);
361
362 #ifdef __WIN32__
363 gst_default_registry_add_path("./");
364 #endif
365
366 ui->pi->play = gst_element_factory_make("playbin", "play");
367 if (!ui->pi->play)
368 {
369 put_status_message(_(" error: cannot create gstreamer playbin\n"), ui);
370 return;
371 }
372
373 gtk_widget_show_all(ui->gui->playlist_box);
374
375 ui->pi->_gstreamer_is_running = TRUE;
376 ui->pi->bus = gst_pipeline_get_bus(GST_PIPELINE(ui->pi->play));
377 gst_bus_add_watch(ui->pi->bus, bus_call, ui);
378 gst_object_unref(ui->pi->bus);
379
380 //add the current filename
381 const gchar *fname = get_input_filename(ui->gui);
382 GList *song_list = g_list_append(NULL, strdup(fname));
383 gstreamer_add_files(song_list, ui);
384 g_list_foreach(song_list, (GFunc)g_free, NULL);
385 g_list_free(song_list);
386 }
387
389 void gstreamer_select_last_file(ui_state *ui)
390 {
391 }
392
394 void gstreamer_play_last_file(ui_state *ui)
395 {
396 gstreamer_stop(ui);
397 gstreamer_play(ui);
398 }
399
401 void gstreamer_add_files(GList *list, ui_state *ui)
402 {
403 player_infos *pi = ui->pi;
404
405 if (pi->song_title) { pi->song_title = NULL; }
406 if (pi->song_artist) { pi->song_artist = NULL; }
407
408 if (!ui->pi->play)
409 {
410 return;
411 }
412
413 gint i = 0;
414 gchar *song = NULL;
415 while ((song = g_list_nth_data(list, i)) != NULL)
416 {
417 if (!song)
418 {
419 i++;
420 continue;
421 }
422
423 add_playlist_file(song, ui);
424
425 gchar *uri = g_filename_to_uri(song, NULL, NULL);
426 g_object_set(G_OBJECT(ui->pi->play), "uri", uri, NULL);
427 if (uri) { g_free(uri); }
428
429 i++;
430 }
431 }
432
434 void gstreamer_set_volume(gint volume, ui_state *ui)
435 {
436 if (ui->pi->play)
437 {
438 //values between 0 and 2
439 //-documentation says values can be between 0 and 10
440 g_object_set(G_OBJECT(ui->pi->play), "volume", (double) volume / 100.0 * 2, NULL);
441 }
442 }
443
445 gint gstreamer_get_volume(ui_state *ui)
446 {
447 if (!ui->pi->play)
448 {
449 return 0;
450 }
451
452 //values between 0 and 2
453 //-documentation says values can be between 0 and 10
454 double volume = 0;
455 g_object_get(G_OBJECT(ui->pi->play), "volume", &volume, NULL);
456 return (gint) (volume / 2 * 100);
457 }
458
460 void gstreamer_start_with_songs(GList *list, ui_state *ui)
461 {
462 gstreamer_start(ui);
463 gstreamer_add_files(list, ui);
464 gstreamer_play(ui);
465 }
466
468 gint gstreamer_is_running(ui_state *ui)
469 {
470 return ui->pi->_gstreamer_is_running;
471 }
472
474 gint gstreamer_is_paused(ui_state *ui)
475 {
476 if (!ui->pi->play)
477 {
478 return FALSE;
479 }
480
481 GstState state;
482 gst_element_get_state(ui->pi->play, &state, NULL, GST_CLOCK_TIME_NONE);
483
484 if (state == GST_STATE_PAUSED)
485 {
486 return TRUE;
487 }
488
489 return FALSE;
490 }
491
493 void gstreamer_play(ui_state *ui)
494 {
495 if (!ui->pi->play)
496 {
497 return;
498 }
499
500 GstState state;
501 gst_element_get_state(ui->pi->play, &state, NULL, GST_CLOCK_TIME_NONE);
502 if (state == GST_STATE_PLAYING)
503 {
504 gstreamer_jump(0, ui);
505 }
506
507 gst_element_set_state(ui->pi->play, GST_STATE_PLAYING);
508 }
509
511 void gstreamer_stop(ui_state *ui)
512 {
513 if (!ui->pi->play)
514 {
515 return;
516 }
517
518 gst_element_set_state(ui->pi->play, GST_STATE_NULL);
519 }
520
522 void gstreamer_pause(ui_state *ui)
523 {
524 if (!ui->pi->play)
525 {
526 return;
527 }
528
529 GstState state;
530 gst_element_get_state(ui->pi->play, &state, NULL, GST_CLOCK_TIME_NONE);
531
532 if (state == GST_STATE_PLAYING)
533 {
534 gst_element_set_state(ui->pi->play, GST_STATE_PAUSED);
535 }
536 else
537 {
538 gstreamer_play(ui);
539 }
540 }
541
543 void gstreamer_next(ui_state *ui)
544 {
545 }
546
548 void gstreamer_prev(ui_state *ui)
549 {
550 }
551
553 void gstreamer_jump(gint position, ui_state *ui)
554 {
555 if (!ui->pi->play)
556 {
557 return;
558 }
559
560 gst_element_seek(ui->pi->play,
561 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
562 GST_SEEK_TYPE_SET, position * GST_MSECOND, 0, 0);
563 }
564
566 gint gstreamer_get_total_time(ui_state *ui)
567 {
568 if (!ui->pi->play)
569 {
570 return 0;
571 }
572
573 GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
574 gint time = 0;
575
576 if (gst_element_query(ui->pi->play, query))
577 {
578 gint64 total_time;
579 gst_query_parse_duration(query, NULL, &total_time);
580 time = (gint) (total_time / GST_MSECOND);
581 }
582
583 gst_query_unref(query);
584
585 return time;
586 }
587
589 gint gstreamer_is_playing(ui_state *ui)
590 {
591 if (!ui->pi->play)
592 {
593 return FALSE;
594 }
595
596 GstState state;
597 gst_element_get_state(ui->pi->play, &state, NULL, GST_CLOCK_TIME_NONE);
598 if ((state == GST_STATE_PLAYING) || (state == GST_STATE_PAUSED))
599 {
600 return TRUE;
601 }
602
603 return FALSE;
604 }
605
607 void gstreamer_quit(ui_state *ui)
608 {
609 if (ui->pi->play)
610 {
611 gst_element_set_state(ui->pi->play, GST_STATE_NULL);
612 }
613
614 ui->pi->_gstreamer_is_running = FALSE;
615 }
616
617 #endif
618
player_infos
Definition: ui_types.h:175
get_input_filename
gchar * get_input_filename(gui_state *gui)
Get the name of the input file.
Definition: main_window.c:76
add_playlist_file
void add_playlist_file(const gchar *name, ui_state *ui)
add a row to the table
Definition: player_window.c:3068
gstreamer_select_last_file
void gstreamer_select_last_file(ui_state *ui)
selects the last file in the playlist
Definition: gstreamer_control.c:389
gstreamer_get_time_elapsed
gint gstreamer_get_time_elapsed(ui_state *ui)
returns elapsed time
Definition: gstreamer_control.c:331
gstreamer_get_playlist_number
gint gstreamer_get_playlist_number(ui_state *ui)
returns the number of songs of the playlist
Definition: gstreamer_control.c:262
gstreamer_start
void gstreamer_start(ui_state *ui)
starts gstreamer
Definition: gstreamer_control.c:352
gstreamer_play_last_file
void gstreamer_play_last_file(ui_state *ui)
plays the last file of the playlist
Definition: gstreamer_control.c:394
gstreamer_is_playing
gint gstreamer_is_playing(ui_state *ui)
returns TRUE if gstreamer is playing, else FALSE
Definition: gstreamer_control.c:589
ui_state
Definition: ui_types.h:485
gstreamer_get_filename
gchar * gstreamer_get_filename(ui_state *ui)
returns the filename
Definition: gstreamer_control.c:250
gstreamer_quit
void gstreamer_quit(ui_state *ui)
quits player
Definition: gstreamer_control.c:607
gstreamer_next
void gstreamer_next(ui_state *ui)
changes to next song
Definition: gstreamer_control.c:543
gstreamer_get_title_song
gchar * gstreamer_get_title_song(ui_state *ui)
returns the title of the song
Definition: gstreamer_control.c:271
gstreamer_is_paused
gint gstreamer_is_paused(ui_state *ui)
returns TRUE if gstreamer is paused, if not, FALSE
Definition: gstreamer_control.c:474
gstreamer_get_total_time
gint gstreamer_get_total_time(ui_state *ui)
returns total time of the current song
Definition: gstreamer_control.c:566
put_status_message
void put_status_message(const gchar *text, ui_state *ui)
Output a info message to the status message bar.
Definition: main_window.c:264
gstreamer_get_song_infos
void gstreamer_get_song_infos(gchar *total_infos, ui_state *ui)
Gets information about the&lt; song.
Definition: gstreamer_control.c:177
gstreamer_play
void gstreamer_play(ui_state *ui)
plays a song
Definition: gstreamer_control.c:493
gstreamer_start_with_songs
void gstreamer_start_with_songs(GList *list, ui_state *ui)
starts gstreamer with songs
Definition: gstreamer_control.c:460
gstreamer_stop
void gstreamer_stop(ui_state *ui)
stops a song
Definition: gstreamer_control.c:511
gstreamer_jump
void gstreamer_jump(gint position, ui_state *ui)
jump to time
Definition: gstreamer_control.c:553
gstreamer_get_volume
gint gstreamer_get_volume(ui_state *ui)
returns volume
Definition: gstreamer_control.c:445
gstreamer_set_volume
void gstreamer_set_volume(gint volume, ui_state *ui)
sets volume
Definition: gstreamer_control.c:434
gstreamer_add_files
void gstreamer_add_files(GList *list, ui_state *ui)
add files to the gstreamer playlist
Definition: gstreamer_control.c:401
gstreamer_pause
void gstreamer_pause(ui_state *ui)
pause a song
Definition: gstreamer_control.c:522
gstreamer_prev
void gstreamer_prev(ui_state *ui)
changes to previous song
Definition: gstreamer_control.c:548
gstreamer_is_running
gint gstreamer_is_running(ui_state *ui)
returns TRUE if gstreamer is running; if not, FALSE
Definition: gstreamer_control.c:468