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-2012 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     gtk_widget_show_all(playlist_box);
00396 
00397     _gstreamer_is_running = TRUE;
00398     bus = gst_pipeline_get_bus (GST_PIPELINE (play));
00399     gst_bus_add_watch(bus, bus_call, NULL);
00400     gst_object_unref(bus);
00401 
00402     //add the current filename
00403     const gchar *fname =  inputfilename_get();
00404     GList *song_list = NULL;
00405     song_list = g_list_append(song_list, strdup(fname));
00406     gstreamer_add_files(song_list);
00407     //TODO: free memory from GList *song_list
00408   }
00409         else
00410         {
00411                 enter_threads();
00412                 put_status_message(_(" error: cannot create gstreamer playbin\n"));
00413                 exit_threads();
00414         }
00415 }
00416 
00418 void gstreamer_select_last_file()
00419 {
00420 }
00421 
00423 void gstreamer_play_last_file()
00424 {
00425   gstreamer_stop();
00426   gstreamer_play();
00427 }
00428 
00430 void gstreamer_add_files(GList *list)
00431 {
00432   gchar *song = NULL;
00433   gint i = 0;
00434   gchar *uri = NULL;
00435   int len_uri = 20;
00436 
00437   if (song_title)
00438   {
00439     song_title = NULL;
00440   }
00441   if (song_artist)
00442   {
00443     song_artist = NULL;
00444   }
00445 
00446         if (play)
00447   {
00448     while ((song = g_list_nth_data(list, i)) != NULL)
00449     {
00450       if (song)
00451       {
00452         //add file to playlist
00453         add_playlist_file(song);
00454         len_uri += strlen(song);
00455         uri = malloc(sizeof(char) * len_uri);
00456         g_snprintf(uri,len_uri,"file://%s",song);
00457         g_object_set(G_OBJECT(play), "uri", uri, NULL);
00458         if (uri)
00459         {
00460           g_free(uri);
00461           uri = NULL;
00462         }
00463       }
00464       i++;
00465     }
00466   }
00467 }
00468 
00470 void gstreamer_set_volume(gint volume)
00471 {
00472         if (play)
00473         {
00474                 //values between 0 and 2
00475                 //-documentation says values can be between 0 and 10
00476                 g_object_set(G_OBJECT(play), "volume", (double) volume / 100.0 * 2, NULL);
00477         }
00478 }
00479 
00481 gint gstreamer_get_volume()
00482 {
00483         if (play)
00484         {
00485                 double volume = 0;
00486                 //values between 0 and 2
00487                 //-documentation says values can be between 0 and 10
00488                 g_object_get(G_OBJECT(play), "volume", &volume, NULL);
00489 
00490                 return (gint) (volume / 2 * 100);
00491         }
00492         else
00493         {
00494                 return 0;
00495         }
00496 }
00497 
00499 void gstreamer_start_with_songs(GList *list)
00500 {
00501   gstreamer_start();
00502   gstreamer_add_files(list);
00503   gstreamer_play();
00504 }
00505 
00507 gint gstreamer_is_running()
00508 {
00509   return _gstreamer_is_running;
00510 }
00511 
00513 gint gstreamer_is_paused()
00514 {
00515         if (play)
00516         {
00517                 GstState state;
00518                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00519 
00520                 if (state == GST_STATE_PAUSED)
00521                 {
00522                         return TRUE;
00523                 }
00524                 else
00525                 {
00526                         return FALSE;
00527                 }
00528         }
00529         else
00530         {
00531                 return FALSE;
00532         }
00533 }
00534 
00536 void gstreamer_play()
00537 {
00538         if (play)
00539         {
00540                 GstState state;
00541                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00542 
00543     if (state == GST_STATE_PLAYING)
00544     {
00545       gstreamer_jump(0);
00546     }
00547     else
00548     {
00549       gst_element_set_state(play, GST_STATE_PLAYING);
00550     }
00551   }
00552 }
00553 
00555 void gstreamer_stop()
00556 {
00557         if (play)
00558         {
00559                 gst_element_set_state(play, GST_STATE_NULL);
00560         }
00561 }
00562 
00564 void gstreamer_pause()
00565 {
00566         if (play)
00567         {
00568                 GstState state;
00569                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00570 
00571     if (state == GST_STATE_PLAYING)
00572     {
00573       gst_element_set_state(play, GST_STATE_PAUSED);
00574     }
00575     else
00576     {
00577       gstreamer_play();
00578     }
00579   }
00580 }
00581 
00583 void gstreamer_next()
00584 {
00585 }
00586 
00588 void gstreamer_prev()
00589 {
00590 }
00591 
00593 void gstreamer_jump(gint position)
00594 {
00595         if (play)
00596         {
00597                 gst_element_seek(play,
00598                                 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
00599                                 GST_SEEK_TYPE_SET, position * GST_MSECOND, 0, 0);
00600         }
00601 }
00602 
00604 gint gstreamer_get_total_time()
00605 {
00606         if (play)
00607         {
00608                 GstQuery *query = gst_query_new_duration(GST_FORMAT_TIME);
00609                 gint time = 0;
00610 
00611                 if (gst_element_query(play,query))
00612                 {
00613                         gint64 total_time;
00614                         gst_query_parse_duration (query, NULL, &total_time);
00615                         time = (gint) (total_time / GST_MSECOND);
00616                 }
00617 
00618                 gst_query_unref(query);
00619 
00620                 return time;
00621         }
00622         else
00623         {
00624                 return 0;
00625         }
00626 }
00627 
00629 gint gstreamer_is_playing()
00630 {
00631         if (play)
00632         {
00633                 GstState state;
00634                 gst_element_get_state(play, &state, NULL, GST_CLOCK_TIME_NONE);
00635 
00636                 if ((state == GST_STATE_PLAYING) || (state == GST_STATE_PAUSED))
00637                 {
00638                         return TRUE;
00639                 }
00640                 else
00641                 {
00642                         return FALSE;
00643                 }
00644         }
00645         else
00646         {
00647                 return FALSE;
00648         }
00649 }
00650 
00652 void gstreamer_quit()
00653 {
00654   if (play)
00655   {
00656     gst_element_set_state(play, GST_STATE_NULL);
00657   }
00658   _gstreamer_is_running = FALSE;
00659 }
00660 
00661 #endif
00662