gui_main.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:41k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  *              Bill May        wmay@cisco.com
  20.  */
  21. /*
  22.  * gui_main.cpp - Contains the gtk based gui for this player.
  23.  */
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. #include "player_session.h"
  27. #include "player_media.h"
  28. #include <glib.h>
  29. #include <gtk/gtk.h>
  30. #include "gui_utils.h"
  31. #include "media_utils.h"
  32. #include "player_util.h"
  33. #include "gui_xpm.h"
  34. #include <syslog.h>
  35. #include <rtsp/rtsp_client.h>
  36. #include "our_config_file.h"
  37. #include "playlist.h"
  38. #include <libhttp/http.h>
  39. #include <rtp/debug.h>
  40. #include "codec_plugin_private.h"
  41. /* ??? */
  42. #ifndef LOG_PRI
  43. #define LOG_PRI(p) ((p) & LOG_PRIMASK)
  44. #endif
  45. /* Local variables */
  46. static GtkWidget *main_window;
  47. static GtkWidget *main_vbox;
  48. static GtkWidget *close_menuitem;
  49. static GtkAccelGroup *accel_group = NULL;
  50. static GtkTooltips         *tooltips = NULL;
  51. static GList *playlist = NULL;
  52. static GtkWidget *combo;
  53. static volatile enum {
  54.   PLAYING_NONE,
  55.   PLAYING,
  56.   STOPPED,
  57.   PAUSED,
  58. } play_state = PLAYING_NONE;
  59. static CPlaylist *master_playlist;
  60. static CPlayerSession *psptr = NULL;
  61. static CMsgQueue master_queue;
  62. static GtkWidget *play_button;
  63. static GtkWidget *pause_button;
  64. static GtkWidget *stop_button;
  65. //static GtkWidget *rewind_button;
  66. //static GtkWidget *ff_button;
  67. static GtkWidget *speaker_button;
  68. static GtkWidget *volume_slider;
  69. static GtkWidget *time_slider;
  70. static GtkWidget *time_disp;
  71. static GtkWidget *session_desc[5];
  72. static SDL_mutex *command_mutex;
  73. static int master_looped;
  74. static int master_volume;
  75. static int master_muted;
  76. static int master_fullscreen = 0;
  77. static uint64_t master_time;
  78. static int time_slider_pressed = 0;
  79. static int master_screen_size = 100;
  80. static const char *last_entry = NULL;
  81. static const gchar *last_file = NULL;
  82. static GtkTargetEntry drop_types[] = 
  83. {
  84.   { "text/plain", 0, 1 }
  85. };
  86. static void media_list_query (CPlayerSession *psptr,
  87.       int num_video, 
  88.       video_query_t *vq,
  89.       int num_audio,
  90.       audio_query_t *aq)
  91. {
  92.   if (num_video > 0) {
  93.     if (config.get_config_value(CONFIG_PLAY_VIDEO) != 0) {
  94.       vq[0].enabled = 1;
  95.     } 
  96.   }
  97.   if (num_audio > 0) {
  98.     if (config.get_config_value(CONFIG_PLAY_AUDIO) != 0) {
  99.       aq[0].enabled = 1;
  100.     } 
  101.   }
  102. }
  103. static control_callback_vft_t cc_vft = {
  104.   media_list_query,
  105. };
  106. /*
  107.  * toggle_button_adjust - make sure a toggle button reflects the correct
  108.  * state
  109.  */
  110. static void toggle_button_adjust (GtkWidget *button, int state)
  111. {
  112.   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) == state)
  113.     return;
  114.   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), state);
  115. }
  116. /*
  117.  * close_session - delete the session, and set the various gui pieces
  118.  */
  119. static void close_session (void)
  120. {
  121.   if (psptr != NULL) {
  122.     delete psptr;
  123.     psptr = NULL;
  124.     play_state = PLAYING_NONE;
  125.     gtk_widget_set_sensitive(close_menuitem, 0);
  126.     toggle_button_adjust(play_button, FALSE);
  127.     toggle_button_adjust(pause_button, FALSE);
  128.     toggle_button_adjust(stop_button, FALSE);
  129.     gtk_widget_set_sensitive(stop_button, 0);
  130.     gtk_widget_set_sensitive(play_button, 0);
  131.     gtk_widget_set_sensitive(pause_button, 0);
  132.     gtk_widget_set_sensitive(time_slider, 0);
  133.   }
  134. }
  135. /*
  136.  * When we hit play, adjust the gui
  137.  */
  138. static void adjust_gui_for_play (void)
  139. {
  140.   gtk_widget_set_sensitive(close_menuitem, 1);
  141.   gtk_widget_set_sensitive(play_button, 1);
  142.   gtk_widget_set_sensitive(pause_button, 1);
  143.   gtk_widget_set_sensitive(stop_button, 1);
  144.   if (psptr->session_is_seekable()) {
  145.     gtk_widget_set_sensitive(time_slider, 1);
  146.   }
  147.   play_state = PLAYING;
  148.   toggle_button_adjust(play_button, TRUE);
  149.   toggle_button_adjust(stop_button, FALSE);
  150.   toggle_button_adjust(pause_button, FALSE);
  151.   gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), last_entry);
  152.   gtk_editable_select_region(GTK_EDITABLE(GTK_COMBO(combo)->entry), 0, -1);
  153.   gtk_editable_set_position(GTK_EDITABLE(GTK_COMBO(combo)->entry), -1);
  154.   gtk_widget_grab_focus(combo);
  155. }
  156. static void create_session_from_name (const char *name)
  157. {
  158.   gint x, y, w, h;
  159.   GdkWindow *window;
  160.   window = GTK_WIDGET(main_window)->window;
  161.   gdk_window_get_position(window, &x, &y);
  162.   gdk_window_get_size(window, &w, &h);
  163.   y += h + 40;
  164.   if (config.get_config_value(CONFIG_PLAY_AUDIO) == 0 &&
  165.       config.get_config_value(CONFIG_PLAY_VIDEO) == 0) {
  166.     ShowMessage("Hey Dummy", "You have both audio and video disabled");
  167.     return;
  168.   }
  169.   // If we're already running a session, close it.
  170.   if (psptr != NULL) {
  171.     close_session();
  172.   }
  173.   psptr = new CPlayerSession(&master_queue,
  174.      NULL,
  175.      name);
  176.   if (psptr != NULL) {
  177.     char errmsg[512];
  178.     errmsg[0] = '';
  179.     // See if we can create media for this session
  180.     int ret = parse_name_for_session(psptr, name, errmsg, sizeof(errmsg),
  181.      &cc_vft);
  182.     if (ret >= 0) {
  183.       // Yup - valid session.  Set volume, set up sync thread, and
  184.       // start the session
  185.       if (ret > 0) {
  186. ShowMessage("Warning", errmsg);
  187.       }
  188.       if (master_muted == 0)
  189. psptr->set_audio_volume(master_volume);
  190.       else
  191. psptr->set_audio_volume(0);
  192.       psptr->set_up_sync_thread();
  193.       psptr->set_screen_location(x, y);
  194.       psptr->set_screen_size(master_screen_size / 50, master_fullscreen);
  195.       psptr->play_all_media(TRUE);  // check response here...
  196.     adjust_gui_for_play();
  197.     } else {
  198.       // Nope - display a message
  199.       delete psptr;
  200.       psptr = NULL;
  201.       char buffer[1024];
  202.       snprintf(buffer, sizeof(buffer), "%s cannot be openedn%s", name,
  203.        errmsg);
  204.       ShowMessage("Open error", buffer);
  205.     }
  206.   }
  207. }
  208. /*
  209.  * start a session
  210.  */
  211. static void start_session_from_name (const char *name)
  212. {
  213.   GList *p;
  214.   int in_list = 0;
  215.   // Save the last file, so we can use it next time we do a file open
  216.   if (last_entry != NULL) {
  217.     free((void *)last_entry);
  218.   }
  219.   last_entry = strdup(name);
  220.   if (strncmp("rtsp://", name, strlen("rtsp://")) != 0) {
  221.     if (last_file != NULL) {
  222.       free((void *)last_file);
  223.       last_file = NULL;
  224.     }
  225.     last_file = g_strdup(name);
  226.     config.set_config_string(CONFIG_PREV_DIRECTORY, strdup(last_file));
  227.   }
  228.   // See if entry is already in the list.
  229.   p = g_list_first(playlist);
  230.   while (p != NULL && in_list == 0) {
  231.     if (g_strcasecmp(name, (const gchar *)p->data) == 0) {
  232.       in_list = 1;
  233.     }
  234.     p = g_list_next(p);
  235.   }
  236.   
  237.   SDL_mutexP(command_mutex);
  238.   
  239.   // If we're running a playlist, close it now.
  240.   if (master_playlist != NULL) {
  241.     delete master_playlist;
  242.     master_playlist = NULL;
  243.   }
  244.   // Create a new player session
  245.   const char *suffix = strrchr(name, '.');
  246.   if ((suffix != NULL) && 
  247.       ((strcasecmp(suffix, ".mp4plist") == 0) ||
  248.        (strcasecmp(suffix, ".mxu") == 0) ||
  249.        (strcasecmp(suffix, ".gmp4_playlist") == 0))) {
  250.     const char *errmsg = NULL;
  251.     master_playlist = new CPlaylist(name, &errmsg);
  252.     if (errmsg != NULL) {
  253.       ShowMessage("Playlist error", errmsg);
  254.     } else {
  255.       create_session_from_name(master_playlist->get_first());
  256.     }
  257.   } else {
  258.     create_session_from_name(name);
  259.   }
  260.   // Add this file to the drop down list
  261.   // If we're playing, adjust the gui
  262.   if (psptr != NULL) {
  263.     if (in_list == 0) {
  264.       config.move_config_strings(CONFIG_PREV_FILE_3, CONFIG_PREV_FILE_2);
  265.       config.move_config_strings(CONFIG_PREV_FILE_2, CONFIG_PREV_FILE_1);
  266.       config.move_config_strings(CONFIG_PREV_FILE_1, CONFIG_PREV_FILE_0);
  267.       config.set_config_string(CONFIG_PREV_FILE_0, strdup(name));
  268.     }
  269.   }
  270.   if (in_list == 0) {
  271.     gchar *newone = g_strdup(name);
  272.     playlist = g_list_append(playlist, newone);
  273.     gtk_combo_set_popdown_strings (GTK_COMBO(combo), playlist);
  274.     gtk_widget_show(combo);
  275.   }
  276.   SDL_mutexV(command_mutex);
  277. }
  278. /*
  279.  * delete_event - called when window closed
  280.  */
  281. void delete_event (GtkWidget *widget, gpointer *data)
  282. {
  283.   if (psptr != NULL) {
  284.     delete psptr;
  285.   }
  286.   if (master_playlist != NULL) {
  287.     delete master_playlist;
  288.   }
  289.   close_plugins();
  290.   gtk_main_quit();
  291. }
  292. static void on_main_menu_close (GtkWidget *window, gpointer data)
  293. {
  294.   SDL_mutexP(command_mutex);
  295.   close_session();
  296.   master_fullscreen = 0;
  297.   SDL_mutexV(command_mutex);
  298. }
  299. static void on_main_menu_help (GtkWidget *window, gpointer data)
  300. {
  301. }
  302. static void on_main_menu_about (GtkWidget *window, gpointer data)
  303. {
  304.   char buffer[1024];
  305.   sprintf(buffer,
  306.   "gmp4player Version %s.n"
  307.   "An open source file/streaming MPEG4 playern"
  308.   "Developed by cisco Systems using then"
  309.   "following open source packages:n"
  310.   "n"
  311.   "SDL, SMPEG audio (MP3) from lokigamesn"
  312.   "RTP from UCLn"
  313.   "ISO reference decoder for MPEG4n"
  314.   "FAAC decodern"
  315.   "Xvid decodern"
  316.   "Developed by Bill May, 10/00 to present", VERSION);
  317.   ShowMessage("About gmp4player",buffer);
  318. }
  319. /*
  320.  * on_drag_data_received - copied from gtv, who copied from someone else
  321.  */
  322. static void on_drag_data_received (GtkWidget *widget,
  323.    GdkDragContext *context,
  324.    gint x,
  325.    gint y,
  326.    GtkSelectionData *selection_data,
  327.    guint info,
  328.    guint time)
  329. {
  330.     gchar *temp, *string;
  331.     string = (gchar *)selection_data->data;
  332.     /* remove newline at end of line, and the file:// url header
  333.        at the begining, copied this code from the xmms source */
  334.     temp = strchr(string, 'n');
  335.     if (temp)
  336.     {
  337.         if (*(temp - 1) == 'r')
  338.             *(temp - 1) = '';
  339.         *temp = '';
  340.     }
  341.     if (!strncasecmp(string, "file:", 5))
  342.         string = string + 5;
  343.     start_session_from_name(string);
  344. }
  345. static GtkWidget *filesel;
  346. static void on_filename_selected (GtkFileSelection *selector, 
  347.   gpointer user_data) 
  348. {
  349.   const gchar *name;
  350.   name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(filesel));
  351.   start_session_from_name(name);
  352. }
  353. /*
  354.  * This is right out of the book...
  355.  */
  356. static void on_browse_button_clicked (GtkWidget *window, gpointer data)
  357. {
  358.   filesel = gtk_file_selection_new("Open Media file");
  359.   if (last_file != NULL) {
  360.     gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), last_file);
  361.   }
  362.   gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(filesel));
  363.   gtk_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
  364.       "clicked", 
  365.       GTK_SIGNAL_FUNC(on_filename_selected), 
  366.       filesel);
  367.                              
  368.   /* Ensure that the dialog box is destroyed when the user clicks a button. */
  369.      
  370.   gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
  371.     "clicked", 
  372.     GTK_SIGNAL_FUNC(gtk_widget_destroy),
  373.     GTK_OBJECT(filesel));
  374.   gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button),
  375.     "clicked", 
  376.     GTK_SIGNAL_FUNC(gtk_widget_destroy),
  377.     GTK_OBJECT(filesel));
  378.   
  379.   /* Display that dialog */
  380.      
  381.   gtk_widget_show (filesel);
  382.   
  383. }
  384. static void on_playlist_child_selected (GtkWidget *window, gpointer data)
  385. {
  386.   gchar *entry = 
  387.     gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
  388.   if (strcmp(entry, "") == 0) 
  389.     return;
  390.   if (last_entry && strcmp(entry, last_entry) == 0) 
  391.     return;
  392.   start_session_from_name(entry);
  393. }
  394. static void on_play_list_selected (GtkWidget *window, gpointer data)
  395. {
  396.   gchar *entry = gtk_entry_get_text(GTK_ENTRY(window));
  397.   start_session_from_name(entry);
  398. }
  399. static void on_play_clicked (GtkWidget *window, gpointer data)
  400. {
  401.   int ret;
  402.   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)) == FALSE) {
  403.     if (play_state == PLAYING) {
  404.       toggle_button_adjust(play_button, TRUE);
  405.     }
  406.     return;
  407.   }
  408.   if (psptr == NULL)
  409.     return;
  410.   ret = 0;
  411.   SDL_mutexP(command_mutex);
  412.   switch (play_state) {
  413.   case PAUSED:
  414.     ret = psptr->play_all_media(FALSE);
  415.     break;
  416.   case STOPPED:
  417.     ret = psptr->play_all_media(TRUE, 0.0);
  418.     break;
  419.   default:
  420.     break;
  421.   }
  422.   if (ret == 0)
  423.     adjust_gui_for_play();
  424.   SDL_mutexV(command_mutex);
  425.   if (ret != 0) {
  426.     close_session();
  427.     ShowMessage("Play error", "Error re-starting session");
  428.   }
  429. }
  430. static void do_pause (void)
  431. {
  432.   SDL_mutexP(command_mutex);
  433.   if (psptr != NULL && play_state == PLAYING) {
  434.     play_state = PAUSED;
  435.     toggle_button_adjust(play_button, FALSE);
  436.     toggle_button_adjust(pause_button, TRUE);
  437.     psptr->pause_all_media();
  438.   } else {
  439.     toggle_button_adjust(pause_button, play_state == PAUSED);
  440.   }
  441.   SDL_mutexV(command_mutex);
  442. }
  443. static void on_pause_clicked (GtkWidget *window, gpointer data)
  444. {
  445.   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(pause_button)) == FALSE) {
  446.     if (play_state == PAUSED) {
  447.       toggle_button_adjust(pause_button, TRUE);
  448.     }
  449.     return;
  450.   }
  451.   do_pause();
  452. }
  453. static void on_stop_clicked (GtkWidget *window, gpointer data)
  454. {
  455.   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(stop_button)) == FALSE) {
  456.     if (play_state == STOPPED) {
  457.       toggle_button_adjust(stop_button, TRUE);
  458.     }
  459.     return;
  460.   }
  461.   SDL_mutexP(command_mutex);
  462.   if (psptr != NULL && play_state == PLAYING) {
  463.     play_state = STOPPED;
  464.     toggle_button_adjust(play_button, FALSE);
  465.     toggle_button_adjust(stop_button, TRUE);
  466.     psptr->pause_all_media();
  467.   } else {
  468.     toggle_button_adjust(stop_button, play_state == STOPPED);
  469.   }
  470.   SDL_mutexV(command_mutex);
  471. }
  472. /*
  473.  * Set the speaker button to either mute or playing
  474.  */
  475. static void set_speaker_button (gchar **xpm_data)
  476. {
  477.   GtkWidget *wid;
  478.   wid = CreateWidgetFromXpm(speaker_button, xpm_data);
  479.   FreeChild(speaker_button);
  480.   gtk_container_add(GTK_CONTAINER(speaker_button), wid);
  481. }
  482. static void on_speaker_clicked (GtkWidget *window, gpointer data)
  483. {
  484.   int vol;
  485.   if (master_muted == 0) {
  486.     // mute the puppy
  487.     set_speaker_button(xpm_speaker_muted);
  488.     master_muted = 1;
  489.     vol = 0;
  490.   } else {
  491.     set_speaker_button(xpm_speaker);
  492.     master_muted = 0;
  493.     vol  = master_volume;
  494.   }
  495.   config.set_config_value(CONFIG_MUTED, master_muted);
  496.   if (psptr && psptr->session_has_audio()) {
  497.     psptr->set_audio_volume(vol);
  498.   }
  499. }
  500. static void volume_adjusted (int volume)
  501. {
  502.   GtkAdjustment *val = gtk_range_get_adjustment(GTK_RANGE(volume_slider));
  503.   gtk_adjustment_set_value(val, (gfloat)volume);
  504.   master_volume = volume;
  505.   config.set_config_value(CONFIG_VOLUME, master_volume);
  506.   gtk_range_set_adjustment(GTK_RANGE(volume_slider), val);
  507.   gtk_range_slider_update(GTK_RANGE(volume_slider));
  508.   gtk_range_clear_background(GTK_RANGE(volume_slider));
  509.   //gtk_range_draw_background(GTK_RANGE(volume_slider));
  510.    if (master_muted == 0 && psptr && psptr->session_has_audio()) {
  511.      psptr->set_audio_volume(master_volume);
  512.    }
  513. }
  514. static void on_volume_adjusted (GtkWidget *window, gpointer data)
  515. {
  516.   GtkAdjustment *val = gtk_range_get_adjustment(GTK_RANGE(volume_slider));
  517.   volume_adjusted((int)val->value);
  518. }
  519. static void on_debug_mpeg4isoonly (GtkWidget *window, gpointer data)
  520. {
  521.   GtkCheckMenuItem *checkmenu;
  522.   checkmenu = GTK_CHECK_MENU_ITEM(window);
  523.   config.set_config_value(CONFIG_USE_MPEG4_ISO_ONLY,
  524.   checkmenu->active == FALSE ? 0 : 1);
  525. }
  526. static void on_debug_use_old_mp4_lib (GtkWidget *window, gpointer data)
  527. {
  528.   GtkCheckMenuItem *checkmenu;
  529.   checkmenu = GTK_CHECK_MENU_ITEM(window);
  530.   config.set_config_value(CONFIG_USE_OLD_MP4_LIB,
  531.   checkmenu->active == FALSE ? 0 : 1);
  532. }
  533. static void on_debug_http (GtkWidget *window, gpointer data)
  534. {
  535.   int loglevel = GPOINTER_TO_INT(data);
  536.   http_set_loglevel(LOG_PRI(loglevel));
  537.   config.set_config_value(CONFIG_HTTP_DEBUG, LOG_PRI(loglevel));
  538. }
  539. static void on_debug_rtsp (GtkWidget *window, gpointer data)
  540. {
  541.   int loglevel = GPOINTER_TO_INT(data);
  542.   rtsp_set_loglevel(LOG_PRI(loglevel));
  543.   config.set_config_value(CONFIG_RTSP_DEBUG, LOG_PRI(loglevel));
  544. }
  545.   
  546. static void on_debug_rtp (GtkWidget *window, gpointer data)
  547. {
  548.   int loglevel = GPOINTER_TO_INT(data);
  549.   rtp_set_loglevel(LOG_PRI(loglevel));
  550.   config.set_config_value(CONFIG_RTP_DEBUG, LOG_PRI(loglevel));
  551. }
  552. static void on_debug_sdp (GtkWidget *window, gpointer data)
  553. {
  554.   int loglevel = GPOINTER_TO_INT(data);
  555.   sdp_set_loglevel(LOG_PRI(loglevel));
  556.   config.set_config_value(CONFIG_SDP_DEBUG, LOG_PRI(loglevel));
  557. }
  558. static void on_media_play_audio (GtkWidget *window, gpointer data)
  559. {
  560.   GtkCheckMenuItem *checkmenu;
  561.   checkmenu = GTK_CHECK_MENU_ITEM(window);
  562.   config.set_config_value(CONFIG_PLAY_AUDIO, checkmenu->active);
  563.   if (psptr != NULL) {
  564.     ShowMessage("Warning", "Play audio will not take effect until next session");
  565.   }
  566. }
  567. static void on_media_play_video (GtkWidget *window, gpointer data)
  568. {
  569.   GtkCheckMenuItem *checkmenu;
  570.   checkmenu = GTK_CHECK_MENU_ITEM(window);
  571.   config.set_config_value(CONFIG_PLAY_VIDEO, checkmenu->active);
  572.   if (psptr != NULL) {
  573.     ShowMessage("Warning", "Play video will not take effect until next session");
  574.   }
  575. }
  576. static void on_network_rtp_over_rtsp (GtkWidget *window, gpointer data)
  577. {
  578.   GtkCheckMenuItem *checkmenu;
  579.   checkmenu = GTK_CHECK_MENU_ITEM(window);
  580.   config.set_config_value(CONFIG_USE_RTP_OVER_RTSP,
  581.   checkmenu->active);
  582. }
  583.   
  584. static void on_video_radio (GtkWidget *window, gpointer data)
  585. {
  586.   int newsize = GPOINTER_TO_INT(data);
  587.   if (newsize != master_screen_size) {
  588.     master_screen_size = newsize;
  589.     if (psptr != NULL) {
  590.       psptr->set_screen_size(newsize / 50);
  591.     }
  592.   }
  593. }
  594. static void on_video_fullscreen (GtkWidget *window, gpointer data)
  595. {
  596.   if (psptr != NULL) {
  597.     master_fullscreen = 1;
  598.     psptr->set_screen_size(master_screen_size / 50, 1);
  599.   }
  600. }
  601. static void on_time_slider_pressed (GtkWidget *window, gpointer data)
  602. {
  603.   time_slider_pressed = 1;
  604. }
  605. static void on_time_slider_adjusted (GtkWidget *window, gpointer data)
  606. {
  607.   double maxtime, newtime;
  608.   time_slider_pressed = 0;
  609.   if (psptr == NULL) 
  610.     return;
  611.   maxtime = psptr->get_max_time();
  612.   if (maxtime == 0.0)
  613.     return;
  614.   GtkAdjustment *val = gtk_range_get_adjustment(GTK_RANGE(time_slider));
  615.   newtime = (maxtime * val->value) / 100.0;
  616.   SDL_mutexP(command_mutex);
  617.   if (play_state == PLAYING) {
  618.     psptr->pause_all_media();
  619.   }
  620.   // If we're going all the way back to the beginning, indicate that
  621.   int ret = psptr->play_all_media(newtime == 0.0 ? TRUE : FALSE, newtime);
  622.   if (ret == 0) 
  623.     adjust_gui_for_play();
  624.   SDL_mutexV(command_mutex);
  625.   if (ret == 0) {
  626.     gtk_range_set_adjustment(GTK_RANGE(time_slider), val);
  627.     gtk_range_slider_update(GTK_RANGE(time_slider));
  628.     gtk_range_clear_background(GTK_RANGE(time_slider));
  629.   //gtk_range_draw_background(GTK_RANGE(vol));
  630.   } else {
  631.     close_session();
  632.   }
  633. }
  634. static void on_loop_enabled_button (GtkWidget *widget, gpointer *data)
  635. {
  636.   master_looped = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
  637.   config.set_config_value(CONFIG_LOOPED, master_looped);
  638. }
  639. /*
  640.  * Main timer routine - runs ~every 500 msec
  641.  * Might be able to adjust this to handle just when playing.
  642.  */
  643. static gint main_timer (gpointer raw)
  644. {
  645.   uint64_t play_time;
  646.   if (play_state == PLAYING) {
  647.     double max_time = psptr->get_max_time();
  648.     uint64_t pt = psptr->get_playing_time();
  649.     double playtime = ((double)pt) / 1000.0;
  650.     double val;
  651.     val = max_time;
  652.     if (time_slider_pressed == 0 && 
  653. val > 0.0 &&
  654. psptr->get_session_state() == SESSION_PLAYING) {
  655.       if (playtime < 0) {
  656. val = 0.0;
  657.       } else if (playtime > val) {
  658. val = 100.0;
  659.       } else {
  660. val = (playtime * 100.0) / val;
  661.       }
  662.       GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(time_slider));
  663.       adj->value = val;
  664.       gtk_range_set_adjustment(GTK_RANGE(time_slider), adj);
  665.       gtk_range_slider_update(GTK_RANGE(time_slider));
  666.       gtk_range_clear_background(GTK_RANGE(time_slider));
  667.       gtk_range_draw_background(GTK_RANGE(time_slider));
  668.       gtk_widget_show(time_slider);
  669.     }
  670.     int hr, min, tot;
  671.     tot = (int) playtime;
  672.     hr = tot / 3600;
  673.     tot %= 3600;
  674.     min = tot / 60;
  675.     tot %= 60;
  676.     playtime -= (double)((hr * 3600) + (min * 60));
  677.     if (max_time == 0.0) {
  678.       gchar buffer[30];
  679.       g_snprintf(buffer, 30, "%d:%02d:%04.1f", hr, min, playtime);
  680.       gtk_label_set_text(GTK_LABEL(time_disp), buffer);
  681.     } else {
  682.       int mhr, mmin, msec, mtot;
  683.       mtot = (int)max_time;
  684.       mhr = mtot / 3600;
  685.       mtot %= 3600;
  686.       mmin = mtot / 60;
  687.       msec = mtot % 60;
  688.       gchar buffer[60];
  689.       g_snprintf(buffer, 60, "%d:%02d:%04.1f of %d:%02d:%02d", 
  690.  hr, min, playtime, mhr, mmin, msec);
  691.       gtk_label_set_text(GTK_LABEL(time_disp), buffer);
  692.     }
  693.     
  694.     for (int ix = 0; ix < 4; ix++) {
  695.       const char *text;
  696.       text = psptr->get_session_desc(ix);
  697.       if (text != NULL) {
  698. gtk_label_set_text(GTK_LABEL(session_desc[ix]), text);
  699.       } else {
  700. gtk_label_set_text(GTK_LABEL(session_desc[ix]), "");
  701.       }
  702.     }
  703.   }
  704.   CMsg *newmsg;
  705.   while ((newmsg = master_queue.get_message()) != NULL) {
  706.     switch (newmsg->get_value()) {
  707.     case MSG_RECEIVED_QUIT:
  708.       //player_debug_message("received quit");
  709.       on_main_menu_close(NULL, 0);
  710.       break;
  711.     case MSG_SESSION_FINISHED:
  712.       player_debug_message("gui received finished message");
  713.       if (master_playlist != NULL) {
  714. SDL_mutexP(command_mutex);
  715. const char *start;
  716. do {
  717.   start = master_playlist->get_next();
  718.   if (start == NULL) {
  719.     if (master_looped)
  720.       start = master_playlist->get_first();
  721.   }
  722.   if (start != NULL)
  723.     create_session_from_name(start);
  724. } while (start != NULL && psptr == NULL);
  725. SDL_mutexV(command_mutex);
  726.       } else if (master_looped != 0) {
  727. if (play_state == PLAYING) {
  728.   if (psptr == NULL)
  729.     break;
  730.   SDL_mutexP(command_mutex);
  731.   psptr->pause_all_media();
  732.   psptr->play_all_media(TRUE, 0.0);
  733.   adjust_gui_for_play();
  734.   SDL_mutexV(command_mutex);
  735. }
  736.       } else if (psptr != NULL) {
  737. play_state = STOPPED;
  738. toggle_button_adjust(play_button, FALSE);
  739. toggle_button_adjust(stop_button, TRUE);
  740. psptr->pause_all_media();
  741. master_fullscreen = 0;
  742.       }
  743.       break;
  744.     case MSG_SDL_KEY_EVENT:
  745.       sdl_event_msg_t *msg;
  746.       uint32_t len;
  747.       msg = (sdl_event_msg_t *)newmsg->get_message(len);
  748.       if (len != sizeof(*msg)) {
  749. player_error_message("key event message is wrong size %d %d", 
  750.      len, (int) sizeof(*msg));
  751. break;
  752.       }
  753.       switch (msg->sym) {
  754.       case SDLK_ESCAPE:
  755. player_debug_message("Got escape");
  756. master_fullscreen = 0;
  757. break;
  758.       case SDLK_RETURN:
  759. if ((msg->mod & (KMOD_LALT | KMOD_RALT)) != 0) {
  760.   master_fullscreen = 1;
  761. }
  762. break;
  763.       case SDLK_c:
  764. if ((msg->mod & (KMOD_LCTRL | KMOD_RCTRL)) != 0) {
  765.   on_main_menu_close(NULL, 0);
  766. }
  767. break;
  768.       case SDLK_x:
  769. if ((msg->mod & (KMOD_LCTRL | KMOD_RCTRL)) != 0) {
  770.   delete_event(NULL, 0);
  771. }
  772. break;
  773.       case SDLK_UP:
  774. master_volume += 10;
  775. if (master_volume > 100) master_volume = 100;
  776. volume_adjusted(master_volume);
  777. break;
  778.       case SDLK_DOWN:
  779. if (master_volume > 10) {
  780.   master_volume -= 10;
  781. } else {
  782.   master_volume = 0;
  783. }
  784. volume_adjusted(master_volume);
  785. break;
  786.       case SDLK_SPACE:
  787. if (play_state == PLAYING) {
  788.   do_pause();
  789. } else if (play_state == PAUSED && psptr) {
  790.   SDL_mutexP(command_mutex);
  791.   if (psptr->play_all_media(FALSE) == 0) {
  792.     adjust_gui_for_play();
  793.     SDL_mutexV(command_mutex);
  794.   } else {
  795.     SDL_mutexV(command_mutex);
  796.     close_session();
  797.   }
  798. }
  799. break;
  800.       case SDLK_HOME:
  801. if (psptr && play_state == PLAYING) {
  802.   psptr->pause_all_media();
  803.   psptr->play_all_media(TRUE, 0.0);
  804. }
  805. break;
  806.       case SDLK_RIGHT:
  807. if (psptr && psptr->session_is_seekable() && play_state == PLAYING) {
  808.   SDL_mutexP(command_mutex);
  809.   play_time = psptr->get_playing_time();
  810.   double ptime, maxtime;
  811.   play_time += 10 * M_LLU;
  812.   ptime = (double)play_time;
  813.   ptime /= 1000.0;
  814.   maxtime = psptr->get_max_time();
  815.   if (ptime < maxtime) {
  816.     psptr->pause_all_media();
  817.     if (psptr->play_all_media(FALSE, ptime) == 0) {
  818.       adjust_gui_for_play();
  819.     } else {
  820.       SDL_mutexV(command_mutex);
  821.       close_session();
  822.       break;
  823.     }
  824.   }
  825.   SDL_mutexV(command_mutex);
  826. }
  827. break;
  828.       case SDLK_LEFT:
  829. if (psptr && psptr->session_is_seekable() && play_state == PLAYING) {
  830.   SDL_mutexP(command_mutex);
  831.   play_time = psptr->get_playing_time();
  832.   double ptime;
  833.   if (play_time >= 10 * M_LLU) {
  834.     play_time -= 10 * M_LLU;
  835.     ptime = (double)play_time;
  836.     ptime /= 1000.0;
  837.     psptr->pause_all_media();
  838.     if (psptr->play_all_media(FALSE, ptime) == 0) {
  839.       adjust_gui_for_play();
  840.     } else {
  841.       SDL_mutexV(command_mutex);
  842.       close_session();
  843.       break;
  844.     }
  845.   }
  846.   SDL_mutexV(command_mutex);
  847. }
  848. break;
  849.       case SDLK_PAGEUP:
  850. if (master_screen_size < 200) {
  851.   master_screen_size *= 2;
  852.   psptr->set_screen_size(master_screen_size / 50);
  853. }
  854. break;
  855.       case SDLK_PAGEDOWN:
  856. if (master_screen_size > 50) {
  857.   master_screen_size /= 2;
  858.   psptr->set_screen_size(master_screen_size / 50);
  859. }
  860. break;
  861.       default:
  862. break;
  863.       }
  864.       break;
  865.     }
  866.   }
  867.   return (TRUE);  // keep timer going
  868. }
  869. /*
  870.  * Main routine - set up window
  871.  */
  872. int main (int argc, char **argv)
  873. {
  874.   gtk_init(&argc, &argv);
  875. printf("%sn", *argv);
  876.   command_mutex = SDL_CreateMutex();
  877.   
  878.   config.read_config_file();
  879.   initialize_plugins();
  880.   if (config.get_config_value(CONFIG_RTP_BUFFER_TIME) != 2) {
  881.     config.set_config_value(CONFIG_RTP_BUFFER_TIME_MSEC, 
  882.     config.get_config_value(CONFIG_RTP_BUFFER_TIME) * 1000);
  883.     config.set_config_value(CONFIG_RTP_BUFFER_TIME,
  884.     config.get_config_default_value(CONFIG_RTP_BUFFER_TIME));
  885.   }
  886.   const char *read;
  887.   playlist = g_list_append(playlist, (void *)"");
  888.   read = config.get_config_string(CONFIG_PREV_FILE_0);
  889.   if (read != NULL) {
  890.     gchar *newone = g_strdup(read);
  891.     playlist = g_list_append(playlist, newone);
  892.   }
  893.   read = config.get_config_string(CONFIG_PREV_FILE_1);
  894.   if (read != NULL) {
  895.     gchar *newone = g_strdup(read);
  896.     playlist = g_list_append(playlist, newone);
  897.   }
  898.   read = config.get_config_string(CONFIG_PREV_FILE_2);
  899.   if (read != NULL) {
  900.     gchar *newone = g_strdup(read);
  901.     playlist = g_list_append(playlist, newone);
  902.   }
  903.   read = config.get_config_string(CONFIG_PREV_FILE_3);
  904.   if (read != NULL) {
  905.     gchar *newone = g_strdup(read);
  906.     playlist = g_list_append(playlist, newone);
  907.   }
  908.   
  909.   last_file = g_strdup(config.get_config_string(CONFIG_PREV_DIRECTORY));
  910.   master_looped = config.get_config_value(CONFIG_LOOPED);
  911.   master_muted = config.get_config_value(CONFIG_MUTED);
  912.   master_volume = config.get_config_value(CONFIG_VOLUME);
  913.   rtsp_set_error_func(player_library_message);
  914.   rtsp_set_loglevel(config.get_config_value(CONFIG_RTSP_DEBUG));
  915.   rtp_set_error_msg_func(player_library_message);
  916.   rtp_set_loglevel(config.get_config_value(CONFIG_RTP_DEBUG));
  917.   sdp_set_error_func(player_library_message);
  918.   sdp_set_loglevel(config.get_config_value(CONFIG_SDP_DEBUG));
  919.   http_set_error_func(player_library_message);
  920.   http_set_loglevel(config.get_config_value(CONFIG_HTTP_DEBUG));
  921.   /*
  922.    * Set up main window
  923.    */
  924.   main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  925.   gtk_window_set_policy(GTK_WINDOW(main_window), FALSE, TRUE, FALSE);
  926.   gtk_window_set_title(GTK_WINDOW(main_window), 
  927.        "cisco Open Source MPEG4 Player");
  928.   gtk_widget_set_uposition(GTK_WIDGET(main_window), 10, 10);
  929.   gtk_widget_set_usize(main_window, 450, 185);
  930.   gtk_window_set_default_size(GTK_WINDOW(main_window), 450, 185);
  931.   gtk_signal_connect(GTK_OBJECT(main_window),
  932.      "delete_event",
  933.      GTK_SIGNAL_FUNC(delete_event),
  934.      NULL);
  935.   main_vbox = gtk_vbox_new(FALSE, 1);
  936.   gtk_widget_show(main_vbox);
  937.   // add stuff
  938.   accel_group = gtk_accel_group_new();
  939.   gtk_accel_group_attach(accel_group, GTK_OBJECT(main_window));
  940.   tooltips = gtk_tooltips_new();
  941.   GtkWidget *menubar, *menu, *menuitem;
  942.   
  943.   menubar = gtk_menu_bar_new();
  944.   gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, FALSE, 0);
  945.   gtk_widget_show(menubar);
  946.   menu = CreateBarSubMenu(menubar, "File");
  947.   menuitem = CreateMenuItem(menu,
  948.     accel_group,
  949.     tooltips,
  950.     "Open",
  951.     "^O",
  952.     "Open local media file",
  953.     GTK_SIGNAL_FUNC(on_browse_button_clicked),
  954.     NULL);
  955.   close_menuitem = CreateMenuItem(menu,
  956.     accel_group,
  957.     tooltips,
  958.     "Close",
  959.     "^C",
  960.     "Close file/stream being viewed",
  961.     GTK_SIGNAL_FUNC(on_main_menu_close),
  962.     NULL);
  963.   // NULL entry is a seperator
  964.   menuitem = CreateMenuItem(menu, 
  965.     accel_group, 
  966.     tooltips, 
  967.     NULL, NULL, NULL, 
  968.     NULL, NULL);
  969.   menuitem = CreateMenuItem(menu,
  970.     accel_group,
  971.     tooltips,
  972.     "Exit",
  973.     "^X",
  974.     "Exit program",
  975.     GTK_SIGNAL_FUNC(delete_event),
  976.     NULL);
  977.   menu = CreateBarSubMenu(menubar, "Media");
  978.   GtkWidget *videosub;
  979.   videosub = CreateSubMenu(menu, "Video");
  980.   GSList *videosizelist = NULL;
  981.   GtkWidget *videoradio;
  982.   videoradio = CreateMenuRadio(videosub,
  983.        "50 %",
  984.        &videosizelist,
  985.        GTK_SIGNAL_FUNC(on_video_radio),
  986.        GINT_TO_POINTER(50));
  987.   videoradio = CreateMenuRadio(videosub,
  988.        "100 %",
  989.        &videosizelist,
  990.        GTK_SIGNAL_FUNC(on_video_radio),
  991.        GINT_TO_POINTER(100));
  992.   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(videoradio), TRUE);
  993.   videoradio = CreateMenuRadio(videosub,
  994.        "200 %",
  995.        &videosizelist,
  996.        GTK_SIGNAL_FUNC(on_video_radio),
  997.        GINT_TO_POINTER(200));
  998.   menuitem = CreateMenuItem(videosub, 
  999.     accel_group, 
  1000.     tooltips, 
  1001.     NULL, NULL, NULL, 
  1002.     NULL, NULL);
  1003.   menuitem = CreateMenuItem(videosub,
  1004.     accel_group,
  1005.     tooltips,
  1006.     "Full Screen",
  1007.     "M-<enter>",
  1008.     "Full Screen",
  1009.     GTK_SIGNAL_FUNC(on_video_fullscreen),
  1010.     NULL);
  1011.   menuitem = CreateMenuCheck(menu, 
  1012.      "Play Audio", 
  1013.      GTK_SIGNAL_FUNC(on_media_play_audio),
  1014.      NULL,
  1015.      config.get_config_value(CONFIG_PLAY_AUDIO));
  1016.   menuitem = CreateMenuCheck(menu, 
  1017.      "Play Video", 
  1018.      GTK_SIGNAL_FUNC(on_media_play_video),
  1019.      NULL,
  1020.      config.get_config_value(CONFIG_PLAY_VIDEO));
  1021.   menu = CreateBarSubMenu(menubar, "Network");
  1022.   menuitem = CreateMenuCheck(menu,
  1023.      "Use RTP over RTSP(TCP)",
  1024.      GTK_SIGNAL_FUNC(on_network_rtp_over_rtsp),
  1025.      NULL,
  1026.      config.get_config_value(CONFIG_USE_RTP_OVER_RTSP));
  1027.   menu = CreateBarSubMenu(menubar, "Help");
  1028.   menuitem = CreateMenuItem(menu,
  1029.     accel_group,
  1030.     tooltips,
  1031.     "Help",
  1032.     NULL,
  1033.     NULL,
  1034.     GTK_SIGNAL_FUNC(on_main_menu_help),
  1035.     NULL);
  1036.   CreateMenuItemSeperator(menu);
  1037.   GtkWidget *debugsub;
  1038.   debugsub = CreateSubMenu(menu, "Debug");
  1039.   menuitem = CreateMenuCheck(debugsub, 
  1040.      "Mpeg4ISOOnly",
  1041.      GTK_SIGNAL_FUNC(on_debug_mpeg4isoonly),
  1042.      NULL,
  1043.      config.get_config_value(CONFIG_USE_MPEG4_ISO_ONLY) == 0 ? FALSE : TRUE);
  1044.   menuitem = CreateMenuCheck(debugsub, 
  1045.      "Use Old mp4 library",
  1046.      GTK_SIGNAL_FUNC(on_debug_use_old_mp4_lib),
  1047.      NULL,
  1048.      config.get_config_value(CONFIG_USE_OLD_MP4_LIB) == 0 ? FALSE : TRUE);
  1049.   CreateLogLevelSubmenu(debugsub, 
  1050. "HTTP library", 
  1051. config.get_config_value(CONFIG_HTTP_DEBUG),
  1052. GTK_SIGNAL_FUNC(on_debug_http));
  1053.   CreateLogLevelSubmenu(debugsub, 
  1054. "RTSP library", 
  1055. config.get_config_value(CONFIG_RTSP_DEBUG),
  1056. GTK_SIGNAL_FUNC(on_debug_rtsp));
  1057.   CreateLogLevelSubmenu(debugsub, 
  1058. "RTP library", 
  1059. config.get_config_value(CONFIG_RTP_DEBUG),
  1060. GTK_SIGNAL_FUNC(on_debug_rtp));
  1061.   CreateLogLevelSubmenu(debugsub, 
  1062. "SDP library", 
  1063. config.get_config_value(CONFIG_SDP_DEBUG),
  1064. GTK_SIGNAL_FUNC(on_debug_sdp));
  1065.   CreateMenuItemSeperator(menu);
  1066.   menuitem = CreateMenuItem(menu,
  1067.     accel_group,
  1068.     tooltips, 
  1069.     "About",
  1070.     NULL,
  1071.     NULL,
  1072.     GTK_SIGNAL_FUNC(on_main_menu_about),
  1073.     NULL);
  1074.   // this is how you turn off the widget
  1075.   gtk_widget_set_sensitive(close_menuitem, 0);
  1076.   GtkWidget *hbox;
  1077.   /*
  1078.    * first line - Play: combo box browse button 
  1079.    */
  1080.   hbox = gtk_hbox_new(FALSE, 1);
  1081.   gtk_widget_show(hbox);
  1082.   gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 5);
  1083.   
  1084.   GtkWidget *label;
  1085.   label = gtk_label_new("Play: ");
  1086.   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
  1087.   gtk_widget_show(label);
  1088.   // combo box uses list playlist.
  1089.   combo = gtk_combo_new();
  1090.   gtk_signal_connect(GTK_OBJECT(GTK_COMBO(combo)->entry),
  1091.      "activate",
  1092.      GTK_SIGNAL_FUNC(on_play_list_selected), 
  1093.      NULL);
  1094.   gtk_signal_connect(GTK_OBJECT(GTK_COMBO(combo)->list),
  1095.      "select_child",
  1096.      GTK_SIGNAL_FUNC(on_playlist_child_selected),
  1097.      combo);
  1098.   gtk_combo_set_popdown_strings (GTK_COMBO(combo), playlist);
  1099.   gtk_combo_set_value_in_list(GTK_COMBO(combo), FALSE, FALSE);
  1100.   gtk_combo_disable_activate(GTK_COMBO(combo));
  1101.   gtk_combo_set_use_arrows_always(GTK_COMBO(combo), 1);
  1102.   gtk_box_pack_start(GTK_BOX(hbox), combo, TRUE, TRUE, 0);
  1103.   gtk_widget_show(combo);
  1104.   /* button for browse */
  1105.   GtkWidget *button;
  1106.   button = gtk_button_new_with_label("Browse");
  1107.   gtk_signal_connect(GTK_OBJECT(button),
  1108.      "clicked",
  1109.      GTK_SIGNAL_FUNC(on_browse_button_clicked),
  1110.      NULL);
  1111.   gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 10);
  1112.   gtk_widget_show(button);
  1113.   /*************************************************************************
  1114.    * 2nd line  play pause stop speaker volume
  1115.    *************************************************************************/
  1116.   hbox = gtk_hbox_new(FALSE, 1);
  1117.   gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 5);
  1118.   gtk_widget_show(hbox);
  1119.   GtkWidget *vbox, *hbox2;
  1120.   vbox = gtk_vbox_new(TRUE, 1);
  1121.   gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
  1122.   gtk_widget_show(vbox);
  1123.   hbox2 = gtk_hbox_new(TRUE, 1);
  1124.   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
  1125.   gtk_widget_show(hbox2);
  1126.   GtkWidget *image;
  1127.   
  1128.   play_button = gtk_toggle_button_new();
  1129.   image = CreateWidgetFromXpm(main_window,xpm_play);
  1130.   gtk_container_add(GTK_CONTAINER(play_button), image);
  1131.   gdk_pixmap_unref((GdkPixmap *)image);
  1132.   gtk_widget_show(play_button);
  1133.   gtk_signal_connect(GTK_OBJECT(play_button),
  1134.      "clicked",
  1135.      GTK_SIGNAL_FUNC(on_play_clicked),
  1136.      NULL);
  1137.   gtk_box_pack_start(GTK_BOX(hbox2), play_button, FALSE, FALSE, 2);
  1138.   pause_button = gtk_toggle_button_new();
  1139.   image = CreateWidgetFromXpm(main_window,xpm_pause);
  1140.   gtk_container_add(GTK_CONTAINER(pause_button), image);
  1141.   gdk_pixmap_unref((GdkPixmap *)image);
  1142.   gtk_widget_show(pause_button);
  1143.   gtk_signal_connect(GTK_OBJECT(pause_button),
  1144.      "clicked",
  1145.      GTK_SIGNAL_FUNC(on_pause_clicked),
  1146.      NULL);
  1147.   gtk_box_pack_start(GTK_BOX(hbox2), pause_button, FALSE, FALSE, 2);
  1148.   stop_button = gtk_toggle_button_new();
  1149.   image = CreateWidgetFromXpm(main_window,xpm_stop);
  1150.   gtk_container_add(GTK_CONTAINER(stop_button), image);
  1151.   gdk_pixmap_unref((GdkPixmap *)image);
  1152.   gtk_widget_show(stop_button);
  1153.   gtk_signal_connect(GTK_OBJECT(stop_button),
  1154.      "clicked",
  1155.      GTK_SIGNAL_FUNC(on_stop_clicked),
  1156.      NULL);
  1157.   gtk_box_pack_start(GTK_BOX(hbox2), stop_button, FALSE, FALSE, 2);
  1158.   gtk_widget_set_sensitive(play_button, 0);
  1159.   gtk_widget_set_sensitive(pause_button, 0);
  1160.   gtk_widget_set_sensitive(stop_button, 0);
  1161.   GtkWidget *sep = gtk_vseparator_new();
  1162.   gtk_widget_show(sep);
  1163.   gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 5);
  1164.   vbox = gtk_vbox_new(FALSE, 1);
  1165.   gtk_widget_show(vbox);
  1166.   gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
  1167.   hbox2 = gtk_hbox_new(FALSE, 1);
  1168.   gtk_widget_show(hbox2);
  1169.   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
  1170.   speaker_button = gtk_button_new();
  1171.   image = CreateWidgetFromXpm(speaker_button,
  1172.       master_muted == 0 ?
  1173.       xpm_speaker : xpm_speaker_muted);
  1174.   gtk_container_add(GTK_CONTAINER(speaker_button), image);
  1175.   gdk_pixmap_unref((GdkPixmap *)image);
  1176.   gtk_widget_show(speaker_button);
  1177.   gtk_signal_connect(GTK_OBJECT(speaker_button),
  1178.      "clicked",
  1179.      GTK_SIGNAL_FUNC(on_speaker_clicked),
  1180.      NULL);
  1181.   gtk_box_pack_start(GTK_BOX(hbox2), speaker_button, FALSE, FALSE, 5);
  1182.   GtkObject *vol_adj;
  1183.   vol_adj = gtk_adjustment_new(master_volume,
  1184.        0.0,
  1185.        100.0,
  1186.        5.0,
  1187.        25.0,
  1188.        0.0);
  1189.   
  1190.   GtkWidget *vol;
  1191.   vol = gtk_hscale_new(GTK_ADJUSTMENT(vol_adj));
  1192.   gtk_scale_set_digits(GTK_SCALE(vol),0);
  1193.   gtk_scale_set_draw_value(GTK_SCALE(vol), 0);
  1194.   gtk_range_set_adjustment ( GTK_RANGE( vol ), GTK_ADJUSTMENT(vol_adj));
  1195.   gtk_range_slider_update ( GTK_RANGE( vol ) );
  1196.   gtk_range_clear_background ( GTK_RANGE( vol ) );
  1197.   //gtk_range_draw_background ( GTK_RANGE( vol ) );
  1198. #if 0
  1199.   // We don't need this - I'm not 100% sure why, but we don't...
  1200.   gtk_signal_connect(vol_adj,
  1201.      "value_changed",
  1202.      GTK_SIGNAL_FUNC(on_volume_adjusted),
  1203.      vol);
  1204. #endif
  1205.   gtk_signal_connect(GTK_OBJECT(vol), 
  1206.      "button_release_event",
  1207.      GTK_SIGNAL_FUNC(on_volume_adjusted),
  1208.      vol);
  1209.   gtk_widget_show(vol);
  1210.   volume_slider = vol;
  1211.   gtk_box_pack_start(GTK_BOX(hbox2), vol, TRUE, TRUE, 0);
  1212.   
  1213.   // boxes for Looped label 
  1214.   sep = gtk_vseparator_new();
  1215.   gtk_widget_show(sep);
  1216.   gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, FALSE, 5);
  1217.   vbox = gtk_vbox_new(TRUE, 1);
  1218.   gtk_widget_show(vbox);
  1219.   gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
  1220.   hbox2 = gtk_hbox_new(TRUE, 1);
  1221.   gtk_widget_show(hbox2);
  1222.   gtk_box_pack_start(GTK_BOX(vbox), hbox2, FALSE, FALSE, 0);
  1223.   GtkWidget *loop_enabled_button;
  1224.   loop_enabled_button = gtk_check_button_new_with_label("Looped");
  1225.   gtk_box_pack_start(GTK_BOX(hbox2), loop_enabled_button, FALSE, FALSE, 0);
  1226.   gtk_signal_connect(GTK_OBJECT(loop_enabled_button),
  1227.      "toggled",
  1228.      GTK_SIGNAL_FUNC(on_loop_enabled_button),
  1229.      loop_enabled_button);
  1230.   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(loop_enabled_button),
  1231.        master_looped);
  1232.   gtk_widget_show(loop_enabled_button);
  1233.   
  1234.   /* 
  1235.    * 3rd line - where we are meter...
  1236.    */
  1237.   hbox = gtk_hbox_new(FALSE, 5);
  1238.   gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
  1239.   gtk_widget_show(hbox);
  1240.   GtkObject *time_slider_adj;
  1241.   master_time = 0;
  1242.   time_slider_adj = gtk_adjustment_new(0.0,
  1243.   0.0,
  1244.   100.0,
  1245.   0.5,
  1246.   0.5,
  1247.   0.5);
  1248.   
  1249.   time_slider = gtk_hscale_new(GTK_ADJUSTMENT(time_slider_adj));
  1250.   gtk_widget_ref(time_slider);
  1251.   gtk_range_set_update_policy(GTK_RANGE(time_slider), GTK_UPDATE_DELAYED);
  1252.   gtk_scale_set_digits(GTK_SCALE(time_slider),0);
  1253.   gtk_scale_set_draw_value(GTK_SCALE(time_slider), 0);
  1254.   gtk_range_set_adjustment(GTK_RANGE(time_slider), 
  1255.    GTK_ADJUSTMENT(time_slider_adj));
  1256.   gtk_range_slider_update(GTK_RANGE(time_slider));
  1257.   gtk_range_clear_background(GTK_RANGE( time_slider));
  1258.   //gtk_range_draw_background(GTK_RANGE(time_slider));
  1259.   gtk_signal_connect(GTK_OBJECT(time_slider), 
  1260.      "button_release_event",
  1261.      GTK_SIGNAL_FUNC(on_time_slider_adjusted),
  1262.      time_slider);
  1263.   gtk_signal_connect(GTK_OBJECT(time_slider),
  1264.      "button_press_event",
  1265.      GTK_SIGNAL_FUNC(on_time_slider_pressed),
  1266.      NULL);
  1267.   gtk_widget_set_sensitive(time_slider, 0);
  1268.   gtk_widget_show(time_slider);
  1269.   gtk_box_pack_start(GTK_BOX(hbox), time_slider, TRUE, TRUE, 0);
  1270.   /* 
  1271.    * 4th line - time display...
  1272.    */
  1273.   hbox = gtk_hbox_new(FALSE, 1);
  1274.   gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
  1275.   gtk_widget_show(hbox);
  1276.   
  1277.   time_disp = gtk_label_new("0:00:00");
  1278.   gtk_widget_ref(time_disp);
  1279.   gtk_widget_show(time_disp);
  1280.   gtk_box_pack_start(GTK_BOX(hbox), time_disp, TRUE, TRUE,0);
  1281.   // session information
  1282.   for (int ix = 0; ix < 4; ix++) {
  1283.     hbox = gtk_hbox_new(FALSE, 1);
  1284.     gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, FALSE, 0);
  1285.     gtk_widget_show(hbox);
  1286.   
  1287.     session_desc[ix] = gtk_label_new("");
  1288.     gtk_widget_ref(session_desc[ix]);
  1289.     gtk_widget_show(session_desc[ix]);
  1290.     gtk_box_pack_start(GTK_BOX(hbox), session_desc[ix], TRUE, TRUE,0);
  1291.   }
  1292.   gtk_timeout_add(500, main_timer, main_window);
  1293.   gtk_container_add(GTK_CONTAINER(main_window), main_vbox);
  1294.   gtk_widget_show(main_window);
  1295.   /*
  1296.    * set up drag and drop
  1297.    */
  1298.   gtk_drag_dest_set(main_window, 
  1299.     GTK_DEST_DEFAULT_ALL, 
  1300.     drop_types,
  1301.     1, 
  1302.     GDK_ACTION_COPY);
  1303.   gtk_signal_connect(GTK_OBJECT(main_window), 
  1304.      "drag_data_received",
  1305.      GTK_SIGNAL_FUNC(on_drag_data_received),
  1306.      main_window);
  1307.   /*
  1308.    * any args passed ?
  1309.    */
  1310.   argc--;
  1311.   argv++;
  1312.   if (argc > 0) {
  1313.     start_session_from_name(*argv);
  1314.   }
  1315.   gtk_main();
  1316.   exit(0);
  1317. }
  1318. /* end gui_main.cpp */