mp3splt-gtk

- Main Page
- Related Pages
- Modules
- 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-2012 Alexandru Munteanu
7 * Contact: io_fx@yahoo.fr
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 #include <stdlib.h>
43 #include <gtk/gtk.h>
44 #include <glib/gi18n.h>
45 #include <time.h>
46 #include <unistd.h>
47 #include <string.h>
48
49 #ifndef NO_GSTREAMER
50 #include <gst/gst.h>
51 #include "gstreamer_control.h"
52 #endif
53
54 #include "player.h"
55 #include "main_win.h"
56 #include "utilities.h"
57 #include "player_tab.h"
58 #include "mp3splt-gtk.h"
59
60 extern int selected_player;
61
62 #ifndef NO_GSTREAMER
63
64 const gchar *song_artist = NULL;
65 const gchar *song_title = NULL;
66 gint rate = 0;
67
68 GstElement *play = NULL;
69 GstBus *bus = NULL;
70 gint _gstreamer_is_running = FALSE;
71 extern GtkWidget *playlist_box;
72 extern GtkWidget *player_vbox;
73
74 extern void add_playlist_file(const gchar *name);
75
77 static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
78 {
79 switch (GST_MESSAGE_TYPE(msg))
80 {
81 case GST_MESSAGE_ERROR:
82 {
83 gchar *debug;
84 GError *error;
85
86 gst_message_parse_error (msg, &error, &debug);
87 g_free(debug);
88
89 gchar *message = NULL;
90 if (error->message != NULL)
91 {
92 gint malloc_size = strlen(error->message) + 20;
93 message = malloc(sizeof(char) * malloc_size);
94 if (message)
95 {
96 memset(message,'\0',malloc_size);
97 g_snprintf(message, malloc_size,_("gstreamer error: %s"),error->message);
98
99 enter_threads();
100 put_status_message(message);
101 exit_threads();
102
103 g_free(message);
104 }
105 }
106 g_error_free(error);
107 break;
108 }
109 case GST_MESSAGE_WARNING:
110 {
111 gchar *debug;
112 GError *error;
113
114 gst_message_parse_warning(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,_("Warning: %s"),error->message);
126
127 enter_threads();
128 put_status_message(message);
129 exit_threads();
130
131 g_free(message);
132 }
133 }
134 g_error_free (error);
135 break;
136 }
137 case GST_MESSAGE_INFO:
138 {
139 gchar *debug;
140 GError *error;
141
142 gst_message_parse_info(msg, &error, &debug);
143 g_free(debug);
144
145 gchar *message = NULL;
146 if (error->message != NULL)
147 {
148 gint malloc_size = strlen(error->message) + 20;
149 message = malloc(sizeof(char) * malloc_size);
150 if (message)
151 {
152 memset(message,'\0',malloc_size);
153 g_snprintf(message, malloc_size,_("Info: %s"),error->message);
154
155 enter_threads();
156 put_status_message(message);
157 exit_threads();
158
159 g_free(message);
160 }
161 }
162 g_error_free (error);
163 break;
164 }
165 case GST_MESSAGE_TAG:
166 {
167 GstTagList *tag_list = NULL;
168 gst_message_parse_tag(msg, &tag_list);
169
170 gint number_of_stream = 0;
171 g_object_get(play, "current-audio", &number_of_stream, NULL);
172
173 //artist
174 const GValue *val = gst_tag_list_get_value_index(tag_list, GST_TAG_ARTIST,
175 number_of_stream);
176 if (val != NULL)
177 {
178 song_artist = g_value_get_string(val);
179 }
180
181 //title
182 val = gst_tag_list_get_value_index(tag_list, GST_TAG_TITLE, number_of_stream);
183 if (val != NULL)
184 {
185 song_title = g_value_get_string(val);
186 }
187
188 //rate (bps)
189 val = gst_tag_list_get_value_index(tag_list, GST_TAG_BITRATE, number_of_stream);
190 if (val != NULL)
191 {
192 rate = g_value_get_uint(val);
193 }
194
195 break;
196 }
197 default:
198 break;
199 }
200
201 return TRUE;
202 }
203
205 void gstreamer_get_song_infos(gchar *total_infos)
206 {
207 if (play)
208 {
209 gint freq = 0;
210 gint nch = 0;
211
212 gint number_of_stream = 0;
213 g_object_get(play, "current-audio", &number_of_stream, NULL);
214
215 //get the stream info
216 GList *streaminfo = NULL;
217 g_object_get(play, "stream-info", &streaminfo, NULL);
218
219 gchar rate_str[32] = { '\0' };
220 gchar freq_str[32] = { '\0' };
221 gchar nch_str[32] = { '\0' };
222
223 gchar *_Kbps = _("Kbps");
224 gchar *_Khz = _("Khz");
225
226 //get the first element of the stream info list
227 GObject *object = g_list_nth_data(streaminfo, number_of_stream);
228 if (object)
229 {
230 GstObject *obj = NULL;
231 g_object_get(G_OBJECT(object), "object", &obj, NULL);
232
233 //get the caps from the first element
234 GstCaps *caps = NULL;
235 g_object_get(obj, "caps", &caps, NULL);
236 if (caps)
237 {
238 //get the structure from the caps
239 GstStructure *structure = NULL;
240 structure = gst_caps_get_structure(caps, number_of_stream);
241
242 //get the rate and the number of channels from the structure
243 gst_structure_get_int(structure, "rate", &freq);
244 gst_structure_get_int(structure, "channels", &nch);
245
246 gst_caps_unref(caps);
247 }
248
249 g_snprintf(rate_str,32, "%d", rate/1000);
250 g_snprintf(freq_str,32, "%d", freq/1000);
251
252 if (nch >= 2)
253 {
254 snprintf(nch_str, 32, "%s", _("stereo"));
255 }
256 else
257 {
258 snprintf(nch_str, 32, "%s", _("mono"));
259 }
260 }
261
262 if (rate != 0)
263 {
264 g_snprintf(total_infos,512,
265 "%s %s %s %s %s",
266 rate_str,_Kbps,freq_str, _Khz,nch_str);
267 }
268 else
269 {
270 total_infos[0] = '\0';
271 }
272 }
273 }
274
279 gchar *gstreamer_get_filename()
280 {
281 return strdup(inputfilename_get());
282 }
283
285 gint gstreamer_get_playlist_number()
286 {
287 return 1;
288 }
289
294 gchar *gstreamer_get_title_song()
295 {
296 if (song_artist || song_title)
297 {
298 gint title_size = 20;
299
300 if (song_artist)
301 {
302 title_size += strlen(song_artist);
303 }
304
305 if (song_title)
306 {
307 title_size += strlen(song_title);
308 }
309
310 gchar *title = malloc(sizeof(char) * title_size);
311 memset(title, title_size, '\0');
312
313 if (song_artist && song_title)
314 {
315 g_snprintf(title, title_size, "%s - %s", song_artist, song_title);
316 }
317 else if (song_title && !song_artist)
318 {
319 g_snprintf(title, title_size, "%s", song_title);
320 }
321 else if (song_artist && !song_title)
322 {
323 g_snprintf(title, title_size, "%s", song_artist);
324 }
325
326 return title;
327 }
328 else
329 {
330 gchar *fname = gstreamer_get_filename();
331 if (fname != NULL)
332 {
333 gchar *file = strrchr(fname, G_DIR_SEPARATOR);
334 if (file != NULL)
335 {
336 gchar *alloced_file = strdup(file+1);
337 g_free(fname);
338 fname = NULL;
339 return alloced_file;
340 }
341 else
342 {
343 return fname;
344 }
345 }
346 else
347 {
348 return strdup("-");
349 }
350 }
351 }
352
354 gint gstreamer_get_time_elapsed()
355 {
356 if (play)
357 {
358 GstQuery *query = gst_query_new_position(GST_FORMAT_TIME);
359 gint64 time = 0;
360
361 if (gst_element_query(play, query))
362 {
363 gst_query_parse_position(query, NULL, &time);
364 }
365
366 gst_query_unref(query);
367
368 return (gint) (time / GST_MSECOND);
369 }
370 else
371 {
372 return 0;
373 }
374 }
375
377 void gstreamer_start()
378 {
379 if (play)
380 {
381 gstreamer_quit();
382 gst_object_unref(play);
383 }
384
385 gst_init(NULL, NULL);
386
387 #ifdef __WIN32__
388 gst_default_registry_add_path("./");
389 #endif
390
391 play = gst_element_factory_make("playbin", "play");
392 //if we have started the player
393 if (play)
394 {
395 gtk_widget_show_all(playlist_box);
396
397 _gstreamer_is_running = TRUE;
398 bus = gst_pipeline_get_bus (GST_PIPELINE (play));
399 gst_bus_add_watch(bus, bus_call, NULL);
400 gst_object_unref(bus);
401
402 //add the current filename
403 const gchar *fname = inputfilename_get();
404 GList *song_list = NULL;
405 song_list = g_list_append(song_list, strdup(fname));
406 gstreamer_add_files(song_list);
407 //TODO: free memory from GList *song_list
408 }
409 else
410 {
411 enter_threads();
412 put_status_message(_(" error: cannot create gstreamer playbin\n"));
413 exit_threads();
414 }
415 }
416
418 void gstreamer_select_last_file()
419 {
420 }
421
423 void gstreamer_play_last_file()
424 {
425 gstreamer_stop();
426 gstreamer_play();
427 }
428
430 void gstreamer_add_files(GList *list)
431 {
432 gchar *song = NULL;
433 gint i = 0;
434 gchar *uri = NULL;
435 int len_uri = 20;
436
437 if (song_title)
438 {
439 song_title = NULL;
440 }
441 if (song_artist)
442 {
443 song_artist = NULL;
444 }
445
446 if (play)
447 {
448 while ((song = g_list_nth_data(list, i)) != NULL)
449 {
450 if (song)
451 {
452 //add file to playlist
453 add_playlist_file(song);
454 len_uri += strlen(song);
455 uri = malloc(sizeof(char) * len_uri);
456 g_snprintf(uri,len_uri,"file://%s",song);
457 g_object_set(G_OBJECT(play), "uri", uri, NULL);
458 if (uri)
459 {
460 g_free(uri);
461 uri = NULL;
462 }
463 }
464 i++;
465 }
466 }
467 }
468
470 void gstreamer_set_volume(gint volume)
471 {
472 if (play)
473 {
474 //values between 0 and 2
475 //-documentation says values can be between 0 and 10
476 g_object_set(G_OBJECT(play), "volume", (double) volume / 100.0 * 2, NULL);
477 }
478 }
479
481 gint gstreamer_get_volume()
482 {
483 if (play)
484 {
485 double volume = 0;
486 //values between 0 and 2
487 //-documentation says values can be between 0 and 10
488 g_object_get(G_OBJECT(play), "volume", &volume, NULL);
489
490 return (gint) (volume / 2 * 100);
491 }
492 else
493 {
494 return 0;
495 }
496 }
497
499 void gstreamer_start_with_songs(GList *list)
500 {
501 gstreamer_start();
502 gstreamer_add_files(list);
503 gstreamer_play();
504 }
505
507 gint gstreamer_is_running()
508 {
509 return _gstreamer_is_running;
510 }
511
513 gint gstreamer_is_paused()
514 {
515 if (play)
516 {
517 GstState state;
518 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
519
520 if (state == GST_STATE_PAUSED)
521 {
522 return TRUE;
523 }
524 else
525 {
526 return FALSE;
527 }
528 }
529 else
530 {
531 return FALSE;
532 }
533 }
534
536 void gstreamer_play()
537 {
538 if (play)
539 {
540 GstState state;
541 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
542
543 if (state == GST_STATE_PLAYING)
544 {
545 gstreamer_jump(0);
546 }
547 else
548 {
549 gst_element_set_state(play, GST_STATE_PLAYING);
550 }
551 }
552 }
553
555 void gstreamer_stop()
556 {
557 if (play)
558 {
559 gst_element_set_state(play, GST_STATE_NULL);
560 }
561 }
562
564 void gstreamer_pause()
565 {
566 if (play)
567 {
568 GstState state;
569 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
570
571 if (state == GST_STATE_PLAYING)
572 {
573 gst_element_set_state(play, GST_STATE_PAUSED);
574 }
575 else
576 {
577 gstreamer_play();
578 }
579 }
580 }
581
583 void gstreamer_next()
584 {
585 }
586
588 void gstreamer_prev()
589 {
590 }
591
593 void gstreamer_jump(gint position)
594 {
595 if (play)
596 {
597 gst_element_seek(play,
598 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
599 GST_SEEK_TYPE_SET, position * GST_MSECOND, 0, 0);
600 }
601 }
602
604 gint gstreamer_get_total_time()
605 {
606 if (play)
607 {
608 GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
609 gint time = 0;
610
611 if (gst_element_query(play,query))
612 {
613 gint64 total_time;
614 gst_query_parse_duration (query, NULL, &total_time);
615 time = (gint) (total_time / GST_MSECOND);
616 }
617
618 gst_query_unref(query);
619
620 return time;
621 }
622 else
623 {
624 return 0;
625 }
626 }
627
629 gint gstreamer_is_playing()
630 {
631 if (play)
632 {
633 GstState state;
634 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
635
636 if ((state == GST_STATE_PLAYING) || (state == GST_STATE_PAUSED))
637 {
638 return TRUE;
639 }
640 else
641 {
642 return FALSE;
643 }
644 }
645 else
646 {
647 return FALSE;
648 }
649 }
650
652 void gstreamer_quit()
653 {
654 if (play)
655 {
656 gst_element_set_state(play, GST_STATE_NULL);
657 }
658 _gstreamer_is_running = FALSE;
659 }
660
661 #endif
662