mp3splt-gtk
snackamp_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  * http://mp3splt.sourceforge.net/
00010  *
00011  *********************************************************/
00012 
00013 /**********************************************************
00014  *
00015  * This program is free software; you can redistribute it and/or
00016  * modify it under the terms of the GNU General Public License
00017  * as published by the Free Software Foundation; either version 2
00018  * of the License, or (at your option) any later version.
00019  *
00020  * This program is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  *
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
00028  * USA.
00029  *
00030  *********************************************************/
00031 
00032 /*!********************************************************
00033  * \file 
00034  * Snackamp control
00035  *
00036  * this file contains functions to control the snackamp 
00037  * player
00038  **********************************************************/
00039 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <gtk/gtk.h>
00043 #include <glib/gi18n.h>
00044 #include <glib.h>
00045 #include <glib/gprintf.h>
00046 #include <string.h>
00047 #include <time.h>
00048 #include <ctype.h>
00049 #include <unistd.h>
00050 
00051 #ifdef __WIN32__
00052 #include <winsock2.h>
00053 #define usleep(x) Sleep(x*1000)
00054 #else
00055 #include <netdb.h>
00056 #include <sys/socket.h>
00057 #include <sys/types.h>
00058 #include <netinet/in.h>
00059 #endif
00060 
00061 #include "player.h"
00062 #include "snackamp_control.h"
00063 
00064 //file descriptors for line buffering
00065 FILE *in, *out;
00066 //if we are connected or not
00067 gboolean connected = FALSE;
00068 
00069 #ifdef __WIN32__
00070 SOCKET socket_id;
00071 #else
00072 gint socket_id;
00073 #endif
00074 
00079 gint connect_snackamp(gint port)
00080 {
00081   //socket and internet structures
00082   struct sockaddr_in host;
00083   struct hostent *h;
00084   gint return_err = 0;
00085   
00086 #ifdef __WIN32__
00087   long winsockinit;
00088   WSADATA winsock;
00089   winsockinit = WSAStartup(0x0101,&winsock);
00090 #endif
00091   
00092   //prepare host..
00093   if((h = gethostbyname("localhost"))==NULL)
00094     {
00095       //fprintf(stderr, "could not get host by name\n");
00096       return_err = 1;
00097     }
00098   
00099   //we prepare socket
00100   host.sin_family = AF_INET;
00101   host.sin_addr.s_addr = 
00102     ((struct in_addr *) (h->h_addr)) ->s_addr;
00103   host.sin_port=htons(port);
00104   
00105   //if no error, continue
00106   if (return_err == 0)
00107     {
00108       //initialize socket
00109       if((socket_id=socket(AF_INET, SOCK_STREAM, 0))==-1)
00110         {
00111           //fprintf(stderr, "error initialising socket\n");
00112           return_err = 2;
00113         }
00114     }
00115   
00116   //if no error, continue
00117   if (return_err == 0)
00118     {
00119       //make connection
00120       if ((connect(socket_id,
00121                    (void *)&host, sizeof(host)))==-1)
00122         {
00123           //fprintf(stderr, "cannot connect to host\n");
00124           return_err = 3;
00125         }
00126     }
00127   
00128   //if no error, continue
00129   if (return_err == 0)
00130     {
00131       /* !@Crap */
00132 #ifdef __WIN32__
00133 #else
00134       //we prepare file descriptors for 
00135       //
00136       if (NULL==(in=fdopen(socket_id, "r")) || 
00137           NULL==(out=fdopen(socket_id, "w")))
00138         {
00139           //fprintf(stderr, "cannot prepare file descriptors..\n");
00140           return_err = 4;
00141         }
00142 #endif  
00143     }
00144   
00145   //if no err
00146   if (return_err == 0)
00147     {
00148       //we set the line buffering
00149       setvbuf(out, NULL, _IOLBF, 0);
00150       connected = TRUE;
00151     }
00152   
00153   //if socket errors, disconnect snackamp
00154   if (return_err >= 2)
00155     disconnect_snackamp();
00156   
00157   return return_err;
00158 }
00159 
00160 gchar *cut_begin_end(gchar *result)
00161 {
00162   //we cut the beginning OK
00163   gchar *test;
00164   
00165   if (strchr(result,' ') != NULL)
00166     {
00167       test = strchr(result, ' ');
00168       g_snprintf(result, strlen(result),
00169                  "%s",test+1);
00170     }
00171   
00172   //we cut the \n at the end
00173   gint result_str = strlen(result);
00174   if (result_str >= 2)
00175     result[result_str - 2] = '\0';
00176   
00177   return result;
00178 }
00179 
00183 gint disconnect_snackamp()
00184 {
00185   connected = FALSE;
00186   //we close the socket
00187 #ifdef __WIN32__
00188   return closesocket(socket_id);
00189 #else
00190   return close(socket_id);
00191 #endif
00192 }
00193 
00199 gchar *snackamp_socket_send_message(gchar *message)
00200 {
00201   gchar *result = malloc(1024 * sizeof(gchar *));
00202   strcpy(result,"disconnected");
00203   
00204 #ifdef __WIN32__
00205   gboolean r = TRUE;
00206   
00207   gint err1 =
00208     send(socket_id, message, strlen(message), 0);
00209   if (err1 <= 0)
00210     {
00211       disconnect_snackamp();
00212     }
00213   else
00214     {
00215       gint err = recv(socket_id, result, 1024, 0);
00216       if (err <= 0)
00217         {
00218           disconnect_snackamp();
00219           r = FALSE;
00220         }
00221     }
00222 #else
00223   //we send message
00224   fputs(message, out);
00225   //we get the result
00226   fgets(result, 1024, in);
00227 #endif
00228 
00229   //if on win32 we put the \0 when we find \n because no line buffering
00230 #ifdef __WIN32__
00231   if (r)
00232     {
00233       if (strchr(result,'\n') != NULL)
00234         {
00235           gchar *line_end;
00236           line_end = strchr(result,'\n') + 1;
00237           *line_end = '\0';
00238         }
00239     }
00240 #endif
00241   
00242   //must be freed after
00243   return result;
00244 }
00245 
00247 gint get_integer_from_string(gchar *result)
00248 {
00249   gint our_integer = 0;
00250   gint i = 0;
00251   gchar *number = NULL;
00252   while ((isdigit(result[i])==0) && 
00253          (result[i]!='\0') && (result[i]!='-'))
00254     {
00255       i++;
00256       number = result + i;
00257     }
00258   if (! (number == (result + strlen(result))))
00259     {
00260       our_integer = atoi (number);
00261     }
00262   
00263   return our_integer;
00264 }
00265 
00267 gboolean snackamp_is_connected()
00268 {
00269   return connected;
00270 }
00271 
00273 void snackamp_get_song_infos(gchar *total_infos)
00274 {
00275   gchar rate_str[32] = { '\0' };
00276   gchar freq_str[32] = { '\0' };
00277   gchar nch_str[32] = { '\0' };
00278   gchar *ptr = NULL;
00279   
00280   gchar *result;
00281   result = snackamp_socket_send_message("xmms_remote_get_info\n");
00282   result = cut_begin_end(result);
00283   
00284   //we get the stereo/mono
00285   char *a = strstr(result, " ");
00286   if (a != NULL)
00287     {
00288       if (strstr(a+1, " ") != NULL)
00289         ptr = strstr(a+1, " ")+1;
00290   
00291       gint i = 0;
00292       //we get the rate
00293       while (result[i] != ' ' 
00294              && isdigit(result[i])
00295              && i<16)
00296         {
00297           g_sprintf(rate_str,
00298                     "%s%c",rate_str,result[i]);
00299           i++;
00300         }
00301       
00302       //we cut the beginning
00303       if (strchr(result, ' ') != NULL)
00304         {
00305           gchar *test;
00306           test = strchr(result,' ');
00307           g_snprintf(result, strlen(result),
00308                      "%s",test+1);
00309         }
00310       
00311       //we get the freq
00312       i = 0;
00313       while (result[i] != ' ' 
00314              && isdigit(result[i])
00315              && i<16)
00316         {
00317           g_sprintf(freq_str,
00318                     "%s%c",freq_str,result[i]);
00319           i++;
00320         }
00321   
00322       //channels int
00323       gint nch;
00324       nch = atoi(ptr);
00325       
00326       if (nch == 2)
00327       {
00328         snprintf(nch_str, 32, "%s", _("stereo"));
00329       }
00330       else
00331       {
00332         snprintf(nch_str, 32, "%s", _("mono"));
00333       }
00334       
00335       gchar *_Kbps = _("Kbps");
00336       gchar *_Khz = _("Khz");
00337       
00338       g_snprintf(total_infos, 512,
00339                  "%s %s     %s %s    %s", 
00340                  rate_str,_Kbps,freq_str, _Khz,nch_str);
00341     }
00342   else
00343     {
00344       g_snprintf(total_infos, 512,
00345                  "disconnected");
00346     }
00347   
00348   //free memory
00349   g_free(result);
00350 }
00351 
00356 gchar *snackamp_get_filename()
00357 {
00358   //we get the current song position
00359   gchar *result;  
00360   gint playlist_pos = snackamp_get_playlist_pos();
00361   
00362   //we get the current file
00363   gchar temp[100];
00364   g_snprintf(temp, 100,
00365              "%s %d\n",
00366              "xmms_remote_get_playlist_file",playlist_pos);
00367   
00368   result = snackamp_socket_send_message(temp);
00369   result = cut_begin_end(result);
00370 
00371   return result;
00372 }
00373 
00375 gint snackamp_get_playlist_pos()
00376 {
00377   gchar *result;
00378   gint number = 0;
00379   result = snackamp_socket_send_message("xmms_remote_get_playlist_pos\n");
00380   number = get_integer_from_string(result);
00381   g_free(result);
00382   
00383   return number;
00384 }
00385 
00387 void snackamp_stop()
00388 {
00389   gchar *result;
00390   result = snackamp_socket_send_message("xmms_remote_stop\n");
00391   g_free(result);
00392 }
00393 
00395 gint snackamp_get_playlist_number()
00396 {
00397   gchar *result;
00398   gint number = 0;
00399   result = snackamp_socket_send_message("xmms_remote_get_playlist_length\n");
00400   number = get_integer_from_string(result);
00401   g_free(result);
00402   
00403   //if we have no song in the playlist we stop it
00404   if (number == -1)
00405     {
00406       snackamp_stop();
00407     }
00408   
00409   return number;
00410 }
00411 
00416 gchar *snackamp_get_title_song()
00417 {
00418   gchar *result;
00419   gint playlist_pos = snackamp_get_playlist_pos();
00420   
00421   //we get the current file
00422   gchar temp[100];
00423   g_snprintf(temp, 100,"%s %d\n",
00424              "xmms_remote_get_playlist_title",playlist_pos);
00425   result = snackamp_socket_send_message(temp);
00426   result = cut_begin_end(result);
00427   
00428   return result;
00429 }
00430 
00432 gint snackamp_get_time_elapsed()
00433 {
00434   gchar *result;
00435   gint pos;
00436   result = snackamp_socket_send_message("xmms_remote_get_output_time\n");
00437   pos = get_integer_from_string(result);
00438   g_free(result);
00439   
00440   return pos;
00441 }
00442 
00444 void snackamp_start()
00445 {
00446   gint timer;
00447   time_t lt;
00448   
00449   static gchar *exec_command;
00450   exec_command = "snackAmp";
00451   gchar *exec_this = g_strdup_printf("%s &", exec_command);
00452   system(exec_this);
00453   
00454   timer = time(&lt);
00455   while ((!snackamp_is_running()) &&
00456          ((time(&lt) - timer) < 8))
00457     {
00458       usleep(0);
00459     }
00460   
00461   g_free(exec_this);
00462 }
00463 
00465 void snackamp_set_playlist_pos(gint pos)
00466 {
00467   gchar *result;
00468   gchar temp[100];
00469   g_snprintf(temp, 100, "%s %d\n",
00470           "xmms_remote_set_playlist_pos",pos);
00471   result = snackamp_socket_send_message(temp);
00472   g_free(result);
00473 }
00474 
00476 void snackamp_select_last_file()
00477 {
00478   //we get last song position
00479   gint last_song = snackamp_get_playlist_number();
00480   snackamp_set_playlist_pos(last_song-1);
00481 }
00482 
00484 void snackamp_play()
00485 {
00486   gchar *result;
00487   result = snackamp_socket_send_message("xmms_remote_play\n");
00488   g_free(result);
00489 }
00490 
00492 void snackamp_play_last_file()
00493 {
00494   snackamp_select_last_file();
00495   snackamp_play();
00496 }
00497 
00499 void snackamp_add_files(GList *list)
00500 {
00501   gchar *song;
00502   gchar *result;
00503   
00504   gint i = 0;
00505   gchar *local;
00506   gint malloc_int;
00507   
00508   //for all songs
00509   while ((song = g_list_nth_data(list, i)) != NULL)
00510     {
00511       malloc_int = strlen(song) + 30;
00512       local = malloc(malloc_int * sizeof(gchar *));
00513       g_snprintf(local,malloc_int,"%s {%s}\n", 
00514                  "xmms_remote_playlist_add ", song);
00515       result = snackamp_socket_send_message(local);
00516       g_free(result);
00517       g_free(local);
00518       i++;
00519     }
00520 }
00521 
00523 void snackamp_set_volume(gint volume)
00524 {
00525   //we get the current file
00526   gchar *result;
00527   gchar temp[100];
00528   g_snprintf(temp, 100, "%s %d\n",
00529           "xmms_remote_set_main_volume",volume);
00530   result = snackamp_socket_send_message(temp);
00531   g_free(result);
00532 }
00533 
00535 gint snackamp_get_volume()
00536 {
00537   gchar *result;
00538   gint vol;
00539   result = snackamp_socket_send_message("xmms_remote_get_main_volume\n");
00540   vol = get_integer_from_string(result);
00541   g_free(result);
00542   
00543   return vol;
00544 }
00545 
00547 void snackamp_start_with_songs(GList *list)
00548 {
00549   snackamp_start();
00550   snackamp_add_files(list);
00551 }
00552 
00554 gint snackamp_is_running()
00555 {
00556   gint result = FALSE;
00557   
00558   //if we are not connected
00559   if (!connected)
00560     {
00561       //if we can connect to snackamp, the player is running
00562       if (connect_snackamp(8775) == 0)
00563         {
00564           result = TRUE;
00565         }
00566     }
00567   else
00568     //if we are connected
00569     {
00570       result = TRUE;
00571     }
00572   
00573   return result;
00574 }
00575 
00577 void snackamp_pause()
00578 {
00579   gchar *result;
00580   result = snackamp_socket_send_message("xmms_remote_pause\n");
00581   g_free(result);
00582 }
00583 
00585 void snackamp_next()
00586 {
00587   gchar *result;
00588   result = snackamp_socket_send_message("xmms_remote_playlist_next\n");
00589   g_free(result);
00590 }
00591 
00593 void snackamp_prev()
00594 {
00595   gint playlist_pos = snackamp_get_playlist_pos();
00596   
00597   //if we are not at the beginning
00598   if (playlist_pos > 0)
00599     {
00600       gchar *result;
00601       result = snackamp_socket_send_message("xmms_remote_playlist_prev\n");
00602       g_free(result);
00603     }
00604   else
00605     {
00606       //we play the last song
00607       snackamp_play_last_file();
00608     }
00609 }
00610 
00612 void snackamp_jump(gint position)
00613 {
00614   //we have the position in miliseconds, we get it in hundreths of
00615   //seconds
00616   gint hundr_secs_pos = position / 10;
00617   //we get only the hundreth of seconds
00618   gint hundr_secs = hundr_secs_pos % 100;
00619   if (hundr_secs == 1)
00620     {
00621       hundr_secs = 0;
00622     }
00623   //we have the seconds left
00624   gint secs = hundr_secs_pos / 100;
00625   gfloat total_pos = hundr_secs + secs * 100;
00626   total_pos /= 100;
00627   
00628   gchar *result;
00629   gchar temp[100];
00630   g_snprintf(temp, 100, "%s %f\n",
00631              "xmms_remote_jump_to_time", 
00632              total_pos);
00633   
00634   result = snackamp_socket_send_message(temp);
00635   g_free(result);
00636 }
00637 
00639 gint snackamp_get_total_time()
00640 {
00641   gchar *result;
00642   gint hundr_secs;
00643   result = snackamp_socket_send_message("xmms_remote_get_playlist_time\n");
00644   //we get and convert to hundreth of seconds
00645   hundr_secs = get_integer_from_string(result) * 1000;
00646   g_free(result);
00647   
00648   return hundr_secs;
00649 }
00650 
00652 gint snackamp_is_playing()
00653 {
00654   //if we are connected to snackamp
00655   if (snackamp_is_connected())
00656     {
00657       gchar *result;
00658       gint i;
00659       result = snackamp_socket_send_message("xmms_remote_is_playing\n");
00660       i = atoi(result);
00661       g_free(result);
00662       
00663       if (i == 0)
00664         return FALSE;
00665       else
00666         return TRUE;
00667     }
00668   else
00669     return FALSE;
00670 }
00671 
00676 gint snackamp_is_paused()
00677 {
00678   //if we are connected to snackamp
00679   if (snackamp_is_connected())
00680     {
00681       gint i;
00682       gchar *result;
00683       result = snackamp_socket_send_message("xmms_remote_is_paused\n");
00684       result = cut_begin_end(result);
00685       
00686       i = atoi(result);
00687       g_free(result);
00688       
00689       if (i == 1)
00690         return TRUE;
00691       else
00692         return FALSE;
00693     }
00694   else
00695     return FALSE;
00696 }
00697 
00698 /*//quits player
00699 gint snackamp_quit()
00700 {
00701   return 1;
00702 }
00703 */