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: 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 
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 
263 {
264  return 1;
265 }
266 
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 
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 
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 
390 {
391 }
392 
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 
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 
469 {
470  return ui->pi->_gstreamer_is_running;
471 }
472 
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 
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 
512 {
513  if (!ui->pi->play)
514  {
515  return;
516  }
517 
518  gst_element_set_state(ui->pi->play, GST_STATE_NULL);
519 }
520 
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 
544 {
545 }
546 
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 
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 
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 
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