mp3splt-gtk
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 
280 {
281  return strdup(inputfilename_get());
282 }
283 
286 {
287  return 1;
288 }
289 
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 
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 
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 
419 {
420 }
421 
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 
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 
508 {
509  return _gstreamer_is_running;
510 }
511 
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 
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 
556 {
557  if (play)
558  {
559  gst_element_set_state(play, GST_STATE_NULL);
560  }
561 }
562 
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 
584 {
585 }
586 
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 
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 
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 
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