📄 gui_main.cpp
字号:
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is MPEG4IP.
*
* The Initial Developer of the Original Code is Cisco Systems Inc.
* Portions created by Cisco Systems Inc. are
* Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved.
*
* Contributor(s):
* Bill May wmay@cisco.com
*/
/*
* gui_main.cpp - Contains the gtk based gui for this player.
*/
#include <stdlib.h>
#include <stdio.h>
#include "player_session.h"
#include "player_media.h"
#include <glib.h>
#include <gtk/gtk.h>
#include "gui_utils.h"
#include "media_utils.h"
#include "player_util.h"
#include "gui_xpm.h"
#include <syslog.h>
#include <rtsp/rtsp_client.h>
#include "our_config_file.h"
#include "playlist.h"
#include <libhttp/http.h>
#include <rtp/debug.h>
#include "codec_plugin_private.h"
/* ??? */
#ifndef LOG_PRI
#define LOG_PRI(p) ((p) & LOG_PRIMASK)
#endif
/* Local variables */
static GtkWidget *main_window;
static GtkWidget *main_vbox;
static GtkWidget *close_menuitem;
static GtkAccelGroup *accel_group = NULL;
static GtkTooltips *tooltips = NULL;
static GList *playlist = NULL;
static GtkWidget *combo;
static volatile enum {
PLAYING_NONE,
PLAYING,
STOPPED,
PAUSED,
} play_state = PLAYING_NONE;
static CPlaylist *master_playlist;
static CPlayerSession *psptr = NULL;
static CMsgQueue master_queue;
static GtkWidget *play_button;
static GtkWidget *pause_button;
static GtkWidget *stop_button;
//static GtkWidget *rewind_button;
//static GtkWidget *ff_button;
static GtkWidget *speaker_button;
static GtkWidget *volume_slider;
static GtkWidget *time_slider;
static GtkWidget *time_disp;
static GtkWidget *session_desc[5];
static SDL_mutex *command_mutex;
static int master_looped;
static int master_volume;
static int master_muted;
static int master_fullscreen = 0;
static uint64_t master_time;
static int time_slider_pressed = 0;
static int master_screen_size = 100;
static const char *last_entry = NULL;
static const gchar *last_file = NULL;
static GtkTargetEntry drop_types[] =
{
{ "text/plain", 0, 1 }
};
static void media_list_query (CPlayerSession *psptr,
int num_video,
video_query_t *vq,
int num_audio,
audio_query_t *aq)
{
if (num_video > 0) {
if (config.get_config_value(CONFIG_PLAY_VIDEO) != 0) {
vq[0].enabled = 1;
}
}
if (num_audio > 0) {
if (config.get_config_value(CONFIG_PLAY_AUDIO) != 0) {
aq[0].enabled = 1;
}
}
}
static control_callback_vft_t cc_vft = {
media_list_query,
};
/*
* toggle_button_adjust - make sure a toggle button reflects the correct
* state
*/
static void toggle_button_adjust (GtkWidget *button, int state)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) == state)
return;
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), state);
}
/*
* close_session - delete the session, and set the various gui pieces
*/
static void close_session (void)
{
if (psptr != NULL) {
delete psptr;
psptr = NULL;
play_state = PLAYING_NONE;
gtk_widget_set_sensitive(close_menuitem, 0);
toggle_button_adjust(play_button, FALSE);
toggle_button_adjust(pause_button, FALSE);
toggle_button_adjust(stop_button, FALSE);
gtk_widget_set_sensitive(stop_button, 0);
gtk_widget_set_sensitive(play_button, 0);
gtk_widget_set_sensitive(pause_button, 0);
gtk_widget_set_sensitive(time_slider, 0);
}
}
/*
* When we hit play, adjust the gui
*/
static void adjust_gui_for_play (void)
{
gtk_widget_set_sensitive(close_menuitem, 1);
gtk_widget_set_sensitive(play_button, 1);
gtk_widget_set_sensitive(pause_button, 1);
gtk_widget_set_sensitive(stop_button, 1);
if (psptr->session_is_seekable()) {
gtk_widget_set_sensitive(time_slider, 1);
}
play_state = PLAYING;
toggle_button_adjust(play_button, TRUE);
toggle_button_adjust(stop_button, FALSE);
toggle_button_adjust(pause_button, FALSE);
gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), last_entry);
gtk_editable_select_region(GTK_EDITABLE(GTK_COMBO(combo)->entry), 0, -1);
gtk_editable_set_position(GTK_EDITABLE(GTK_COMBO(combo)->entry), -1);
gtk_widget_grab_focus(combo);
}
static void create_session_from_name (const char *name)
{
gint x, y, w, h;
GdkWindow *window;
window = GTK_WIDGET(main_window)->window;
gdk_window_get_position(window, &x, &y);
gdk_window_get_size(window, &w, &h);
y += h + 40;
if (config.get_config_value(CONFIG_PLAY_AUDIO) == 0 &&
config.get_config_value(CONFIG_PLAY_VIDEO) == 0) {
ShowMessage("Hey Dummy", "You have both audio and video disabled");
return;
}
// If we're already running a session, close it.
if (psptr != NULL) {
close_session();
}
psptr = new CPlayerSession(&master_queue,
NULL,
name);
if (psptr != NULL) {
char errmsg[512];
errmsg[0] = '\0';
// See if we can create media for this session
int ret = parse_name_for_session(psptr, name, errmsg, sizeof(errmsg),
&cc_vft);
if (ret >= 0) {
// Yup - valid session. Set volume, set up sync thread, and
// start the session
if (ret > 0) {
ShowMessage("Warning", errmsg);
}
if (master_muted == 0)
psptr->set_audio_volume(master_volume);
else
psptr->set_audio_volume(0);
psptr->set_up_sync_thread();
psptr->set_screen_location(x, y);
psptr->set_screen_size(master_screen_size / 50, master_fullscreen);
psptr->play_all_media(TRUE); // check response here...
adjust_gui_for_play();
} else {
// Nope - display a message
delete psptr;
psptr = NULL;
char buffer[1024];
snprintf(buffer, sizeof(buffer), "%s cannot be opened\n%s", name,
errmsg);
ShowMessage("Open error", buffer);
}
}
}
/*
* start a session
*/
static void start_session_from_name (const char *name)
{
GList *p;
int in_list = 0;
// Save the last file, so we can use it next time we do a file open
if (last_entry != NULL) {
free((void *)last_entry);
}
last_entry = strdup(name);
if (strncmp("rtsp://", name, strlen("rtsp://")) != 0) {
if (last_file != NULL) {
free((void *)last_file);
last_file = NULL;
}
last_file = g_strdup(name);
config.set_config_string(CONFIG_PREV_DIRECTORY, strdup(last_file));
}
// See if entry is already in the list.
p = g_list_first(playlist);
while (p != NULL && in_list == 0) {
if (g_strcasecmp(name, (const gchar *)p->data) == 0) {
in_list = 1;
}
p = g_list_next(p);
}
SDL_mutexP(command_mutex);
// If we're running a playlist, close it now.
if (master_playlist != NULL) {
delete master_playlist;
master_playlist = NULL;
}
// Create a new player session
const char *suffix = strrchr(name, '.');
if ((suffix != NULL) &&
((strcasecmp(suffix, ".mp4plist") == 0) ||
(strcasecmp(suffix, ".mxu") == 0) ||
(strcasecmp(suffix, ".gmp4_playlist") == 0))) {
const char *errmsg = NULL;
master_playlist = new CPlaylist(name, &errmsg);
if (errmsg != NULL) {
ShowMessage("Playlist error", errmsg);
} else {
create_session_from_name(master_playlist->get_first());
}
} else {
create_session_from_name(name);
}
// Add this file to the drop down list
// If we're playing, adjust the gui
if (psptr != NULL) {
if (in_list == 0) {
config.move_config_strings(CONFIG_PREV_FILE_3, CONFIG_PREV_FILE_2);
config.move_config_strings(CONFIG_PREV_FILE_2, CONFIG_PREV_FILE_1);
config.move_config_strings(CONFIG_PREV_FILE_1, CONFIG_PREV_FILE_0);
config.set_config_string(CONFIG_PREV_FILE_0, strdup(name));
}
}
if (in_list == 0) {
gchar *newone = g_strdup(name);
playlist = g_list_append(playlist, newone);
gtk_combo_set_popdown_strings (GTK_COMBO(combo), playlist);
gtk_widget_show(combo);
}
SDL_mutexV(command_mutex);
}
/*
* delete_event - called when window closed
*/
void delete_event (GtkWidget *widget, gpointer *data)
{
if (psptr != NULL) {
delete psptr;
}
if (master_playlist != NULL) {
delete master_playlist;
}
close_plugins();
gtk_main_quit();
}
static void on_main_menu_close (GtkWidget *window, gpointer data)
{
SDL_mutexP(command_mutex);
close_session();
master_fullscreen = 0;
SDL_mutexV(command_mutex);
}
static void on_main_menu_help (GtkWidget *window, gpointer data)
{
}
static void on_main_menu_about (GtkWidget *window, gpointer data)
{
char buffer[1024];
sprintf(buffer,
"gmp4player Version %s.\n"
"An open source file/streaming MPEG4 player\n"
"Developed by cisco Systems using the\n"
"following open source packages:\n"
"\n"
"SDL, SMPEG audio (MP3) from lokigames\n"
"RTP from UCL\n"
"ISO reference decoder for MPEG4\n"
"FAAC decoder\n"
"Xvid decoder\n"
"Developed by Bill May, 10/00 to present", VERSION);
ShowMessage("About gmp4player",buffer);
}
/*
* on_drag_data_received - copied from gtv, who copied from someone else
*/
static void on_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
gint x,
gint y,
GtkSelectionData *selection_data,
guint info,
guint time)
{
gchar *temp, *string;
string = (gchar *)selection_data->data;
/* remove newline at end of line, and the file:// url header
at the begining, copied this code from the xmms source */
temp = strchr(string, '\n');
if (temp)
{
if (*(temp - 1) == '\r')
*(temp - 1) = '\0';
*temp = '\0';
}
if (!strncasecmp(string, "file:", 5))
string = string + 5;
start_session_from_name(string);
}
static GtkWidget *filesel;
static void on_filename_selected (GtkFileSelection *selector,
gpointer user_data)
{
const gchar *name;
name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(filesel));
start_session_from_name(name);
}
/*
* This is right out of the book...
*/
static void on_browse_button_clicked (GtkWidget *window, gpointer data)
{
filesel = gtk_file_selection_new("Open Media file");
if (last_file != NULL) {
gtk_file_selection_set_filename(GTK_FILE_SELECTION(filesel), last_file);
}
gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(filesel));
gtk_signal_connect (GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
"clicked",
GTK_SIGNAL_FUNC(on_filename_selected),
filesel);
/* Ensure that the dialog box is destroyed when the user clicks a button. */
gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
"clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
GTK_OBJECT(filesel));
gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button),
"clicked",
GTK_SIGNAL_FUNC(gtk_widget_destroy),
GTK_OBJECT(filesel));
/* Display that dialog */
gtk_widget_show (filesel);
}
static void on_playlist_child_selected (GtkWidget *window, gpointer data)
{
gchar *entry =
gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(combo)->entry));
if (strcmp(entry, "") == 0)
return;
if (last_entry && strcmp(entry, last_entry) == 0)
return;
start_session_from_name(entry);
}
static void on_play_list_selected (GtkWidget *window, gpointer data)
{
gchar *entry = gtk_entry_get_text(GTK_ENTRY(window));
start_session_from_name(entry);
}
static void on_play_clicked (GtkWidget *window, gpointer data)
{
int ret;
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(play_button)) == FALSE) {
if (play_state == PLAYING) {
toggle_button_adjust(play_button, TRUE);
}
return;
}
if (psptr == NULL)
return;
ret = 0;
SDL_mutexP(command_mutex);
switch (play_state) {
case PAUSED:
ret = psptr->play_all_media(FALSE);
break;
case STOPPED:
ret = psptr->play_all_media(TRUE, 0.0);
break;
default:
break;
}
if (ret == 0)
adjust_gui_for_play();
SDL_mutexV(command_mutex);
if (ret != 0) {
close_session();
ShowMessage("Play error", "Error re-starting session");
}
}
static void do_pause (void)
{
SDL_mutexP(command_mutex);
if (psptr != NULL && play_state == PLAYING) {
play_state = PAUSED;
toggle_button_adjust(play_button, FALSE);
toggle_button_adjust(pause_button, TRUE);
psptr->pause_all_media();
} else {
toggle_button_adjust(pause_button, play_state == PAUSED);
}
SDL_mutexV(command_mutex);
}
static void on_pause_clicked (GtkWidget *window, gpointer data)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -