mp3splt-gtk
gstreamer_control.c
Go to the documentation of this file.
00001 /**********************************************************
00002  *
00003  * mp3splt-gtk -- utility based on mp3splt,
00004  *                for mp3/ogg splitting without decoding
00005  *
00006  * Copyright: (C) 2005-2011 Alexandru Munteanu
00007  * Contact: io_fx@yahoo.fr
00008  *
00009  * from BMP to Audacious patch from Roberto Neri - 2007,2008
00010  *
00011  * http://mp3splt.sourceforge.net/
00012  *
00013  *********************************************************/
00014 
00015 /**********************************************************
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License
00019  * as published by the Free Software Foundation; either version 2
00020  * of the License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful,
00023  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025  * GNU General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
00030  * USA.
00031  *
00032  *********************************************************/
00033 
00034 /*!*******************************************************
00035  * \file 
00036  * Control the gstreamer framework
00037  *
00038  * this file has functions to control the 'internal' 
00039  + gstreamer player
00040  *********************************************************/
00041 
00042 #include <stdlib.h>
00043 #include <gtk/gtk.h>
00044 #include <glib/gi18n.h>
00045 #include <time.h>
00046 #include <unistd.h>
00047 #include <string.h>
00048 
00049 #ifndef NO_GSTREAMER
00050 #include <gst/gst.h>
00051 #include "gstreamer_control.h"
00052 #endif
00053 
00054 #include "player.h"
00055 #include "main_win.h"
00056 #include "utilities.h"
00057 #include "player_tab.h"
00058 #include "mp3splt-gtk.h"
00059 
00060 extern int selected_player;
00061 
00062 #ifndef NO_GSTREAMER
00063 
00064 const gchar *song_artist = NULL;
00065 const gchar *song_title = NULL;
00066 gint rate = 0;
00067 
00068 GstElement *play = NULL;
00069 GstBus *bus = NULL;
00070 gint _gstreamer_is_running = FALSE;
00071 extern GtkWidget *playlist_box;
00072 extern GtkWidget *player_vbox;
00073 
00074 extern void add_playlist_file(const gchar *name);
00075 
00077 static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
00078 {
00079   switch (GST_MESSAGE_TYPE(msg))
00080   {
00081     case GST_MESSAGE_ERROR:
00082     {
00083       gchar  *debug;
00084       GError *error;
00085 
00086       gst_message_parse_error (msg, &error, &debug);
00087       g_free(debug);
00088 
00089       gchar *message = NULL;
00090       if (error->message != NULL)
00091       {
00092         gint malloc_size = strlen(error->message) + 20;
00093         message = malloc(sizeof(char) * malloc_size);
00094         if (message)
00095         {
00096           memset(message,'\0',malloc_size);
00097           g_snprintf(message, malloc_size,_("gstreamer error: %s"),error->message);
00098 
00099           enter_threads();
00100           put_status_message(message);
00101           exit_threads();
00102 
00103           g_free(message);
00104         }
00105       }
00106       g_error_free(error);
00107       break;
00108     }
00109     case GST_MESSAGE_WARNING:
00110     {
00111       gchar  *debug;
00112       GError *error;
00113 
00114       gst_message_parse_warning(msg, &error, &debug);
00115       g_free(debug);
00116 
00117       gchar *message = NULL;
00118       if (error->message != NULL)
00119       {
00120         gint malloc_size = strlen(error->message) + 20;
00121         message = malloc(sizeof(char) * malloc_size);
00122         if (message)
00123         {
00124           memset(message,'\0',malloc_size);
00125           g_snprintf(message, malloc_size,_("Warning: %s"),error->message);
00126 
00127           enter_threads();
00128           put_status_message(message);
00129           exit_threads();
00130 
00131           g_free(message);
00132         }
00133       }
00134       g_error_free (error);
00135       break;
00136     }
00137     case GST_MESSAGE_INFO:
00138     {
00139       gchar  *debug;
00140       GError *error;
00141 
00142       gst_message_parse_info(msg, &error, &debug);
00143       g_free(debug);
00144 
00145       gchar *message = NULL;
00146       if (error->message != NULL)
00147       {
00148         gint malloc_size = strlen(error->message) + 20;
00149         message = malloc(sizeof(char) * malloc_size);
00150         if (message)
00151         {
00152           memset(message,'\0',malloc_size);
00153           g_snprintf(message, malloc_size,_("Info: %s"),error->message);
00154 
00155           enter_threads();
00156           put_status_message(message);
00157           exit_threads();
00158 
00159           g_free(message);
00160         }
00161       }
00162       g_error_free (error);
00163       break;
00164     }
00165     case GST_MESSAGE_TAG:
00166     {
00167       GstTagList *tag_list = NULL;
00168       gst_message_parse_tag(msg, &tag_list);
00169       
00170       gint number_of_stream = 0;
00171       g_object_get(play, "current-audio", &number_of_stream, NULL);
00172 
00173       //artist
00174       const GValue *val = gst_tag_list_get_value_index(tag_list, GST_TAG_ARTIST, 
00175           number_of_stream);
00176       if (val != NULL)
00177       {
00178         song_artist = g_value_get_string(val);
00179       }
00180 
00181       //title
00182       val = gst_tag_list_get_value_index(tag_list, GST_TAG_TITLE, number_of_stream);
00183       if (val != NULL)
00184       {
00185         song_title = g_value_get_string(val);
00186       }
00187 
00188       //rate (bps)
00189       val = gst_tag_list_get_value_index(tag_list, GST_TAG_BITRATE, number_of_stream);
00190       if (val != NULL)
00191       {
00192         rate = g_value_get_uint(val);
00193       }
00194  
00195       break;
00196     }
00197     default:
00198       break;
00199   }
00200 
00201   return TRUE;
00202 }
00203 
00205 void gstreamer_get_song_infos(gchar *total_infos)
00206 {
00207         if (play)
00208         {
00209                 gint freq = 0;
00210                 gint nch = 0;
00211 
00212                 gint number_of_stream = 0;
00213                 g_object_get(play, "current-audio", &number_of_stream, NULL);
00214 
00215                 //get the stream info
00216                 GList *streaminfo = NULL;
00217                 g_object_get(play, "stream-info", &streaminfo, NULL);
00218 
00219                 gchar rate_str[32] = { '\0' };
00220                 gchar freq_str[32] = { '\0' };
00221                 gchar nch_str[32] = { '\0' };
00222 
00223                 gchar *_Kbps = _("Kbps");
00224                 gchar *_Khz = _("Khz");
00225 
00226                 //get the first element of the stream info list
00227                 GObject *object = g_list_nth_data(streaminfo, number_of_stream); 
00228                 if (object)
00229                 {
00230                         GstObject *obj = NULL; 
00231                         g_object_get(G_OBJECT(object), "object", &obj, NULL);
00232 
00233                         //get the caps from the first element
00234                         GstCaps *caps = NULL;
00235                         g_object_get(obj, "caps", &caps, NULL);
00236                         if (caps)
00237                         {
00238                                 //get the structure from the caps
00239                                 GstStructure *structure = NULL;
00240                                 structure = gst_caps_get_structure(caps, number_of_stream);
00241 
00242                                 //get the rate and the number of channels from the structure
00243                                 gst_structure_get_int(structure, "rate", &freq);
00244                                 gst_structure_get_int(structure, "channels", &nch);
00245 
00246                                 gst_caps_unref(caps);
00247                         }
00248 
00249                         g_snprintf(rate_str,32, "%d", rate/1000);
00250                         g_snprintf(freq_str,32, "%d", freq/1000);
00251 
00252                         if (nch >= 2)
00253                         {
00254                                 snprintf(nch_str, 32, "%s", _("stereo"));
00255                         }
00256                         else
00257                         {
00258                                 snprintf(nch_str, 32, "%s", _("mono"));
00259                         }
00260                 }
00261 
00262                 if (rate != 0)
00263                 {
00264                         g_snprintf(total_infos,512,
00265                                         "%s %s     %s %s    %s", 
00266                                         rate_str,_Kbps,freq_str, _Khz,nch_str);
00267                 }
00268                 else 
00269                 {
00270                         total_infos[0] = '\0';
00271                 }
00272         }
00273 }
00274 
00279 gchar *gstreamer_get_filename()
00280 {
00281   return strdup(inputfilename_get());
00282 }
00283 
00285 gint gstreamer_get_playlist_number()
00286 {
00287   return 1;
00288 }
00289 
00294 gchar *gstreamer_get_title_song()
00295 {
00296   if (song_artist || song_title)
00297   {
00298     gint title_size = 20;
00299 
00300     if (song_artist)
00301     {
00302       title_size += strlen(song_artist);
00303     }
00304 
00305     if (song_title)
00306     {
00307       title_size += strlen(song_title);
00308     }
00309 
00310     gchar *title = malloc(sizeof(char) * title_size);
00311     memset(title, title_size, '\0');
00312 
00313     if (song_artist && song_title)
00314     {
00315       g_snprintf(title, title_size, "%s - %s", song_artist, song_title);
00316     }
00317     else if (song_title && !song_artist)
00318     {
00319       g_snprintf(title, title_size, "%s", song_title);
00320     }
00321     else if (song_artist && !song_title)
00322     {
00323       g_snprintf(title, title_size, "%s", song_artist);
00324     }
00325 
00326     return title;
00327   }
00328   else
00329   {
00330     gchar *fname = gstreamer_get_filename();
00331     if (fname != NULL)
00332     {
00333       gchar *file = strrchr(fname, G_DIR_SEPARATOR);
00334       if (file != NULL)
00335       {
00336         gchar *alloced_file = strdup(file+1);
00337         g_free(fname);
00338         fname = NULL;
00339         return alloced_file;
00340       }
00341       else
00342       {
00343         return fname;
00344       }
00345     }
00346     else
00347     {
00348       return strdup("-");
00349     }
00350   }
00351 }
00352 
00354 gint gstreamer_get_time_elapsed()
00355 {
00356         if (play)
00357         {
00358                 GstQuery *query = gst_query_new_position(GST_FORMAT_TIME);
00359                 gint64 time = 0;
00360 
00361                 if (gst_element_query(play, query))
00362                 {
00363                         gst_query_parse_position(query, NULL, &time);
00364                 }
00365 
00366                 gst_query_unref(query);
00367 
00368                 return (gint) (time / GST_MSECOND);
00369         }
00370         else
00371         {
00372                 return 0;
00373         }
00374 }
00375 
00377 void gstreamer_start()
00378 {
00379   if (play)
00380   {
00381     gstreamer_quit();
00382     gst_object_unref(play);
00383   }
00384 
00385   gst_init(NULL, NULL);
00386 
00387 #ifdef __WIN32__
00388   gst_default_registry_add_path("./");
00389 #endif
00390 
00391   play = gst_element_factory_make("playbin", "play");
00392         //if we have started the player
00393   if (play)
00394         {
00395     if (! container_has_child(GTK_CONTAINER(player_vbox), playlist_box))
00396     {
00397       gtk_box_pack_start(GTK_BOX(player_vbox), playlist_box, TRUE, TRUE, 0);
00398     }
00399     gtk_widget_show_all(playlist_box);
00400 
00401                 _gstreamer_is_running = TRUE;
00402                 bus = gst_pipeline_get_bus (GST_PIPELINE (play));
00403                 gst_bus_add_watch(bus, bus_call, NULL);
00404                 gst_object_unref(bus);
00405 
00406                 //add the current filename
00407                 const gchar *fname =  inputfilename_get();
00408                 GList *song_list = NULL;
00409                 song_list = g_list_append(song_list, strdup(fname));
00410                 gstreamer_add_files(song_list);
00411     //TODO: free memory from GList *song_list
00412         }
00413         else
00414         {
00415                 enter_threads();
00416                 put_status_message(_(" error: cannot create gstreamer playbin\n"));
00417                 exit_threads();
00418         }
00419 }
00420 
00422 void gstreamer_select_last_file()
00423 {
00424 }
00425 
00427 void gstreamer_play_last_file()
00428 {
00429   gstreamer_stop();
00430   gstreamer_play();
00431 }
00432 
00434 void gstreamer_add_files(GList *list)
00435 {
00436   gchar *song = NULL;
00437   gint i = 0;
00438   gchar *uri = NULL;
00439   int len_uri = 20;
00440 
00441   if (song_title)
00442   {
00443     song_title = NULL;
00444   }
00445   if (song_artist)
00446   {
00447     song_artist = NULL;
00448   }
00449 
00450         if (play)
00451   {
00452     while ((song = g_list_nth_data(list, i)) != NULL)
00453     {
00454       if (song)
00455       {
00456         //add file to playlist
00457         add_playlist_file(song);
00458         len_uri += strlen(song);
00459         uri = malloc(sizeof(char) * len_uri);
00460         g_snprintf(uri,len_uri,"file://%s",song);
00461         g_object_set(G_OBJECT(play), "uri", uri, NULL);
00462         if (uri)
00463         {
00464           g_free(uri);
00465           uri = NULL;
00466         }
00467       }
00468       i++;
00469     }
00470   }
00471 }
00472 
00474 void gstreamer_set_volume(gint volume)
00475 {
00476         if (play)
00477         {
00478                 //values between 0 and 2
00479                 //-documentation says values can be between 0 and 10
00480                 g_object_set(G_OBJECT(play), "volume", (double) volume / 100.0 * 2, NULL);
00481         }
00482 }
00483 
00485 gint gstreamer_get_volume()
00486 {
00487         if (play)
00488         {
00489                 double volume = 0;
00490                 //values between 0 and 2
00491                 //-documentation says values can be between 0 and 10
00492                 g_object_get(G_OBJECT(play), "volume", &volume, NULL);
00493 
00494                 return (gint) (volume / 2 * 100);
00495         }
00496         else
00497         {
00498                 return 0;
00499         }
00500 }
00501 
00503 void gstreamer_start_with_songs(GList *list)
00504 {
00505   gstreamer_start();
00506   gstreamer_add_files(list);
00507   gstreamer_play();
00508 }
00509 
00511 gint gstreamer_is_running()
00512 {
00513   return _gstreamer_is_running;
00514 }
00515 
00517 gint gstreamer_is_paused()
00518 {
00519         if (play)
00520         {
00521                 GstState state;
00522                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00523 
00524                 if (state == GST_STATE_PAUSED)
00525                 {
00526                         return TRUE;
00527                 }
00528                 else
00529                 {
00530                         return FALSE;
00531                 }
00532         }
00533         else
00534         {
00535                 return FALSE;
00536         }
00537 }
00538 
00540 void gstreamer_play()
00541 {
00542         if (play)
00543         {
00544                 GstState state;
00545                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00546 
00547     if (state == GST_STATE_PLAYING)
00548     {
00549       gstreamer_jump(0);
00550     }
00551     else
00552     {
00553       gst_element_set_state(play, GST_STATE_PLAYING);
00554     }
00555   }
00556 }
00557 
00559 void gstreamer_stop()
00560 {
00561         if (play)
00562         {
00563                 gst_element_set_state(play, GST_STATE_NULL);
00564         }
00565 }
00566 
00568 void gstreamer_pause()
00569 {
00570         if (play)
00571         {
00572                 GstState state;
00573                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00574 
00575     if (state == GST_STATE_PLAYING)
00576     {
00577       gst_element_set_state(play, GST_STATE_PAUSED);
00578     }
00579     else
00580     {
00581       gstreamer_play();
00582     }
00583   }
00584 }
00585 
00587 void gstreamer_next()
00588 {
00589 }
00590 
00592 void gstreamer_prev()
00593 {
00594 }
00595 
00597 void gstreamer_jump(gint position)
00598 {
00599         if (play)
00600         {
00601                 gst_element_seek(play,
00602                                 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
00603                                 GST_SEEK_TYPE_SET, position * GST_MSECOND, 0, 0);
00604         }
00605 }
00606 
00608 gint gstreamer_get_total_time()
00609 {
00610         if (play)
00611         {
00612                 GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
00613                 gint time = 0;
00614 
00615                 if (gst_element_query(play,query))
00616                 {
00617                         gint64 total_time;
00618                         gst_query_parse_duration (query, NULL, &total_time);
00619                         time = (gint) (total_time / GST_MSECOND);
00620                 }
00621 
00622                 gst_query_unref(query);
00623 
00624                 return time;
00625         }
00626         else
00627         {
00628                 return 0;
00629         }
00630 }
00631 
00633 gint gstreamer_is_playing()
00634 {
00635         if (play)
00636         {
00637                 GstState state;
00638                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00639 
00640                 if ((state == GST_STATE_PLAYING) || (state == GST_STATE_PAUSED))
00641                 {
00642                         return TRUE;
00643                 }
00644                 else
00645                 {
00646                         return FALSE;
00647                 }
00648         }
00649         else
00650         {
00651                 return FALSE;
00652         }
00653 }
00654 
00656 void gstreamer_quit()
00657 {
00658   if (play)
00659   {
00660     gst_element_set_state(play, GST_STATE_NULL);
00661   }
00662   _gstreamer_is_running = FALSE;
00663 
00664   gtk_widget_hide(playlist_box);
00665 }
00666 
00667 #endif
00668