blob: be219b594434cb02017de6769d037ab49275921e [file] [log] [blame]
/*
* Copyright (C) 2009-2011 Freescale Semiconductor, Inc. All rights reserved.
*
*/
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include <glib.h>
#include <glib/gprintf.h>
#include <glib/gstdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include "imxplayer.h"
#include "controlbar.h"
#include "infobox.h"
#include "menubar.h"
#include "playlistbox.h"
#include "subtitle.h"
#include "volumebar.h"
#include "playengine.h"
void eos_callback(void* player);
void show_error(void* player, const gchar *error);
void state_change(void* player,
GstState old_st, GstState new_st, GstState pending_st);
static gboolean config_change(GtkWidget *widget, GdkEvent *event, gpointer data)
{
gint w, h;
ImxPlayer *player = (ImxPlayer*)data;
if (GDK_CONFIGURE == event->type) {
gtk_window_get_size(GTK_WINDOW(player->top_window), &w, &h);
//g_print("current window size, %d:%d\n", w, h);
player->window_w = w;
player->window_h = h;
player->video_x = 0;
player->video_w = w;
if (player->fullscreen) {
player->video_h = h;
player->video_y = 0;
} else {
player->video_h = h - CTRLBAR_H - MENUBAR_H;
player->video_y = MENUBAR_H;
}
gtk_widget_set_size_request(player->video_win,
player->video_w, player->video_h);
gtk_fixed_move(GTK_FIXED(player->fixed_ct), player->video_win,
player->video_x, player->video_y);
player->playengine->set_render_rect(player->playengine, 0, 0,
player->video_w, player->video_h);
player->playengine->expose_video(player->playengine);
gtk_fixed_move(GTK_FIXED(player->fixed_ct), player->infobox.info_box,
(w-INFO_BOX_W), MENUBAR_H);
ctrlbar_resize(player->fixed_ct, &player->ctrlbar,
0, h-CTRLBAR_H, w, CTRLBAR_H);
subtitle_resize(player->fixed_ct, &player->subtitle, player->video_x,
player->video_y, player->video_w, player->video_h);
}
// return FALSE to let parent to handle this event further
return FALSE;
}
static gboolean key_press(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
ImxPlayer *player = (ImxPlayer*)data;
switch (event->keyval) {
case GDK_P:
case GDK_p:
case GDK_space:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.play_pause));
break;
#ifdef ENABLE_STOP_BUTTON
case GDK_S:
case GDK_s:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.play_stop));
break;
#endif
case GDK_F:
case GDK_f:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.full));
break;
case GDK_i:
case GDK_I:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.info));
break;
#ifdef ENABLE_REPEAT_MODE_BUTTON
case GDK_R:
case GDK_r:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.repeat));
break;
#endif
#ifdef ENABLE_STEP_SEEK_BUTTON
case GDK_Right:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.step_forward));
break;
case GDK_Left:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.step_rewind));
break;
#endif
case GDK_Page_Up:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.trick_forward));
break;
case GDK_Page_Down:
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.trick_backward));
break;
case GDK_Q:
case GDK_q:
gtk_main_quit();
break;
default:
break;
}
return TRUE;
}
static gboolean button_press(GtkWidget *widget, GdkEvent *event, gpointer data)
{
ImxPlayer *player = (ImxPlayer*)data;
if (GDK_2BUTTON_PRESS == event->type && 0x01 == event->button.button) {
/*
g_print("%d,%d [%d,%d,%d,%d]\n",
(gint)event->button.x_root, (gint)event->button.y_root,
player->video_x, player->video_y, player->video_w, player->video_h);
*/
if ((gint)event->button.x_root < player->video_w + player->video_x &&
(gint)event->button.y_root < player->video_h + player->video_y) {
gtk_button_clicked(GTK_BUTTON(player->ctrlbar.full));
}
}
if (GDK_BUTTON_PRESS == event->type && 0x01 == event->button.button) {
if (player->fullscreen) {
if ((gint)event->button.x_root < player->video_w + player->video_x &&
(gint)event->button.y_root < player->video_h+player->video_y-CTRLBAR_H
&& (gint)event->button.y_root > MENUBAR_H) {
player->show_ctrlbar = !player->show_ctrlbar;
ctrlbar_show(&player->ctrlbar, player->show_ctrlbar);
player->show_menubar = !player->show_menubar;
menubar_show(&player->menubar, player->show_menubar);
if (!player->show_ctrlbar) {
player->show_volbar = FALSE;
volumebar_show(&player->volumebar, player->show_volbar);
}
if (player->show_ctrlbar || player->show_menubar ||
player->show_playlist) {
gdk_window_set_cursor(gtk_widget_get_window(player->top_window),
gdk_cursor_new(GDK_HAND2));
} else {
gdk_window_set_cursor(gtk_widget_get_window(player->top_window),
gdk_cursor_new(GDK_BLANK_CURSOR));
}
}
}
}
return FALSE;
}
static gboolean delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
return FALSE;
}
static void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
static void video_win_realize(GtkWidget * widget, gpointer data)
{
#if GTK_CHECK_VERSION(2,18,0)
// Tell Gtk+/Gdk to create a native window for this widget instead of
// drawing onto the parent widget.
// This is here just for pedagogical purposes, GDK_WINDOW_XID will call
// it as well in newer Gtk versions
if (!gdk_window_ensure_native(gtk_widget_get_window(widget)))
g_error("Couldn't create native window needed for GstVideoOverlay!");
#endif
ImxPlayer *player = ((ImxPlayer*)data);
GtkWidget *win = GTK_WIDGET(widget);
guintptr win_id = (guintptr)(GDK_WINDOW_XID(gtk_widget_get_window(win)));
player->playengine->set_window(player->playengine, win_id);
gdk_window_set_cursor(gtk_widget_get_window(player->top_window),
gdk_cursor_new(GDK_HAND2));
}
#ifdef EXPOSE_VIDEO_FOR_EACH_EXPOSE_EVENT
static void video_expose_cb(GtkWidget * widget, gpointer data)
{
ImxPlayer *player = ((ImxPlayer*)data);
player->playengine->expose_video(player->playengine);
}
#endif
static gboolean position_update_cb(gpointer data) {
gint64 elapsed;
char cur_str[20];
char dur_str[20];
gint hour, minute, second;
gint hour_d, minute_d, second_d;
ImxPlayer *player = (ImxPlayer*)data;
gint64 dur = player->playengine->get_duration(player->playengine);
if (PLAYENGINE_PLAYING == player->playengine->get_state(player->playengine) &&
dur > 0 ) {
elapsed = player->playengine->get_position(player->playengine);
hour = (elapsed/ (gint64)3600000000000);
minute = (elapsed / (gint64)60000000000) - (hour * 60);
second = (elapsed / 1000000000) - (hour * 3600) - (minute * 60);
hour_d = (dur/ (gint64)3600000000000);
minute_d = (dur / (gint64)60000000000) - (hour_d * 60);
second_d = (dur / (gint64)1000000000) - (hour_d * 3600) - (minute_d * 60);
if (hour_d > 0) {
sprintf(cur_str, "%02d:%02d:%02d", hour, minute, second);
sprintf(dur_str, "%02d:%02d:%02d", hour_d, minute_d, second_d);
} else {
sprintf(cur_str, "%02d:%02d", minute, second);
sprintf(dur_str, "%02d:%02d", minute_d, second_d);
}
if (elapsed > 0) {
double value = (elapsed * (((double) 100) / dur));
gtk_range_set_value(GTK_RANGE(player->ctrlbar.progress), value);
gtk_label_set_text(GTK_LABEL(player->ctrlbar.current), cur_str);
gtk_label_set_text(GTK_LABEL(player->ctrlbar.duration), dur_str);
#if 0
if (player->metainfo_refresh) {
infobox_update(player);
menubar_update(player);
player->metainfo_refresh = FALSE;
}
#endif
}
}
return TRUE;
}
static guint imx_player_get_color_key(void)
{
guint key = 0;
const gchar *colorkey = g_getenv ("COLORKEY");
if (colorkey) {
if (strlen(colorkey) > 1)
key = strtoul(colorkey, NULL, 16);
}
return key;
}
#ifdef ENABLE_SET_COLOR_KEY
static void imx_player_set_color_key(guint key)
{
gchar str[10] = {0};
sprintf(str, "%08x", key);
setenv("COLORKEY", str, TRUE);
}
#endif
void eos_callback(void* player)
{
ImxPlayer *imxplayer = (ImxPlayer *)player;
if (imxplayer) {
imxplayer->playlistbox.next(&imxplayer->playlistbox);
}
}
void show_error(void* player, const gchar *error)
{
GtkWidget *dialog;
if (player) {
dialog = gtk_message_dialog_new(
GTK_WINDOW(((ImxPlayer *)player)->top_window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_OK,
"%s", error);
gtk_window_set_title(GTK_WINDOW(dialog), "Error");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
}
void state_change(void* imxplayer,
GstState old_st, GstState new_st, GstState pending_st)
{
if (old_st == GST_STATE_READY && new_st == GST_STATE_PAUSED) {
ImxPlayer *player = (ImxPlayer *)imxplayer;
imx_metadata *meta = &player->meta;
player->playengine->get_metadata(player->playengine, meta);
infobox_update(player);
menubar_update(player);
}
}
int main(int argc, char *argv[])
{
ImxPlayer player = {0};
GdkColor color;
gchar colorstr[8] = {0};
/* check if DISPLAY envionment variable set */
const gchar *disp = g_getenv ("DISPLAY");
if (!disp || strlen(disp) < 2) {
/* DISPLAY not set, set to :0 */
g_setenv("DISPLAY", ":0", TRUE);
}
/* check if ~/.local/share exit, this folder is used to record the recent
* opened file or folder by GTK
*/
gchar s1[64] = {0};
gchar s2[64] = {0};
const gchar *guname = g_get_user_name();
g_sprintf(s1, "/home/%s/.local", guname);
g_sprintf(s2, "/home/%s/.local/share", guname);
if (!g_file_test(s1, G_FILE_TEST_EXISTS)) {
g_mkdir(s1, 0755);
g_mkdir(s2, 0755);
} else {
if (!g_file_test(s2, G_FILE_TEST_EXISTS)) {
g_mkdir(s2, 0755);
} else {
if (!g_file_test(s2, G_FILE_TEST_IS_DIR)) {
g_remove(s2);
g_mkdir(s2, 0755);
}
}
}
/* load gtk style configuration */
if (g_file_test(MY_GTK_STYLE_CONFIG_FILE, G_FILE_TEST_EXISTS)) {
if (g_file_test(SYS_GTK_STYLE_CONFIG_FILE, G_FILE_TEST_EXISTS)) {
system("cp /etc/gtk-2.0/gtkrc ./config/gtkrc.bak");
}
system("cp ./config/gtkrc /etc/gtk-2.0/gtkrc");
}
gtk_init(&argc, &argv);
/* make sure the type is realized */
GtkSettings *gtk_setting = gtk_settings_get_default ();
g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM));
g_type_class_unref (g_type_class_ref (GTK_TYPE_ICON_SIZE));
g_object_set (gtk_setting, "gtk-menu-images", TRUE, NULL);
g_object_set (gtk_setting, "gtk-icon-sizes",
"gtk-menu=20,20:gtk-button=32,32", NULL);
g_object_set (gtk_setting, "gtk-font-name", "Sans Bold 12", NULL);
player.playengine = play_engine_create(&argc, &argv,
eos_callback,
show_error,
state_change);
player.playengine->player = &player;
player.top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
GdkScreen* scr = gtk_window_get_screen( GTK_WINDOW(player.top_window));
player.screen_w = gdk_screen_get_width(scr);
player.screen_h = gdk_screen_get_height(scr);
player.window_w = player.screen_w;
player.window_h = player.screen_h;
gtk_window_set_default_size(GTK_WINDOW(player.top_window),
player.screen_w, player.screen_h);
gdk_color_parse ("Grey", &color);
gtk_widget_modify_bg (player.top_window, GTK_STATE_NORMAL, &color);
#ifdef REMOVE_WINDOW_MANAGER_DECORATION
gtk_window_fullscreen(GTK_WINDOW(window));
gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
#endif
player.fixed_ct = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(player.top_window), player.fixed_ct);
sprintf(colorstr, "#%06x",
RGB565TOCOLORKEY(RGB888TORGB565(imx_player_get_color_key())));
gdk_color_parse (colorstr, &player.color_key);
/* g_print("%08x,%s,%08x,%08x,%08x\n", player.color_key, colorstr,
bg_color.red, bg_color.green, bg_color.blue);*/
menubar_create(&player);
player.video_win = gtk_drawing_area_new();
gtk_fixed_put(GTK_FIXED(player.fixed_ct), player.video_win, 0, MENUBAR_H);
player.video_w = player.window_w;
player.video_h = player.window_h - CTRLBAR_H - MENUBAR_H;
gtk_widget_set_size_request(player.video_win, player.video_w, player.video_h);
gtk_widget_modify_bg (player.video_win, GTK_STATE_NORMAL, &player.color_key);
gtk_widget_add_events (player.top_window, GDK_BUTTON_PRESS_MASK);
gtk_widget_add_events(player.top_window, GDK_STRUCTURE_MASK);
g_signal_connect(player.video_win, "realize",
G_CALLBACK (video_win_realize), &player);
g_signal_connect(G_OBJECT (player.top_window), "delete_event",
G_CALLBACK (delete_event), &player);
g_signal_connect(G_OBJECT (player.top_window), "destroy",
G_CALLBACK (destroy), &player);
g_signal_connect(G_OBJECT (player.top_window), "key-press-event",
G_CALLBACK (key_press), &player);
g_signal_connect(G_OBJECT (player.top_window), "button-press-event",
G_CALLBACK (button_press), &player);
g_signal_connect(G_OBJECT (player.top_window), "configure-event",
G_CALLBACK (config_change), &player);
#ifdef EXPOSE_VIDEO_FOR_EACH_EXPOSE_EVENT
g_signal_connect(player.video_win, "expose-event",
G_CALLBACK (video_expose_cb), &player);
#endif
ctrlbar_create(&player);
infobox_create(&player);
playlistbox_create(&player);
subtitle_create(&player);
volumebar_create(&player);
speedbox_create(&player);
subtitle_set_text(&player.subtitle, "DEMO SUBTITLE TEXT");
// player.metainfo_refresh = TRUE;
player.show_ctrlbar = TRUE;
player.show_menubar = TRUE;
player.show_subtitle = FALSE;
g_timeout_add(1000, position_update_cb, (gpointer)&player);
GtkSettings *default_settings = gtk_settings_get_default();
g_object_set(default_settings, "gtk-button-images", TRUE, NULL);
gtk_widget_show_all(player.top_window);
infobox_show(&player.infobox, player.show_info);
volumebar_show(&player.volumebar, player.show_volbar);
playlistbox_show(&player.playlistbox, player.show_playlist);
speedbox_show(&player.speed, FALSE);
subtitle_show(&player.subtitle, player.show_subtitle);
if (argc > 1) {
player.playlistbox.add_file(&player.playlistbox, argv[1], TRUE, TRUE);
} else {
gtk_window_set_title(GTK_WINDOW(player.top_window), "IMXPlayer");
}
gtk_main();
play_engine_destroy(player.playengine);
/* recover the gtk style configuration */
if (g_file_test(BAK_GTK_STYLE_CONFIG_FILE, G_FILE_TEST_EXISTS)) {
system("cp ./config/gtkrc.bak /etc/gtk-2.0/gtkrc");
g_remove(BAK_GTK_STYLE_CONFIG_FILE);
}
return 0;
}