/* * instance.c -- GTK+ 2 melted gui * Copyright (C) 2012 Maksym Veremeyenko * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include #include #include #if defined(__MINGW32__) #include #endif #include "instance.h" #include "ui.h" #include "opts.h" #include "timecode.h" #include "player.h" #include "library.h" #include "playlist.h" #include "control.h" GtkTargetEntry drag_targets[] = { { (char*) "application/playlist_item_t", 0, 0 } }; static gboolean library_tree_key(GtkWidget *widget, GdkEventKey *event, gpointer data) { instance_t* app = (instance_t*)data; switch(event->keyval) { case GDK_C: case GDK_c: if(event->state & GDK_CONTROL_MASK) { int count; playlist_item_t* items; items = library_get_selected_items(app, &count); if(items) { int i; for(i = 0; i < count; i++) app->clipboard.item[i] = items[i]; app->clipboard.count = count; }; return TRUE; }; break; case GDK_V: case GDK_v: if(event->state & GDK_CONTROL_MASK) { g_warning("CTRL+v\n"); return TRUE; }; break; case GDK_X: case GDK_x: if(event->state & GDK_CONTROL_MASK) { g_warning("CTRL+x\n"); return TRUE; }; break; case GDK_KEY_BackSpace: // omnplay_library_add(app, 0); return TRUE; case GDK_KEY_F5: // omnplay_library_refresh(app); return TRUE; }; return FALSE; }; static gboolean playlist_grid_key(GtkWidget *widget, GdkEventKey *event, gpointer data) { instance_t* app = (instance_t*)data; switch(event->keyval) { case GDK_C: case GDK_c: if(event->state & GDK_CONTROL_MASK) { playlist_item_copy(app); return TRUE; }; break; case GDK_V: case GDK_v: if(event->state & GDK_CONTROL_MASK) { playlist_item_paste(app, 0); return TRUE; }; break; case GDK_X: case GDK_x: if(event->state & GDK_CONTROL_MASK) { playlist_item_copy(app); playlist_delete_selected_items(app); return TRUE; }; break; case GDK_S: case GDK_s: if(event->state & GDK_CONTROL_MASK) { playlist_save(app); return TRUE; }; break; case GDK_O: case GDK_o: if(event->state & GDK_CONTROL_MASK) { playlist_load(app); return TRUE; }; break; case GDK_KEY_uparrow: if(event->state & GDK_CONTROL_MASK) { playlist_item_swap(app, -1); return TRUE; }; break; case GDK_KEY_downarrow: if(event->state & GDK_CONTROL_MASK) { playlist_item_swap(app, -1); return TRUE; }; break; case GDK_KEY_space: control_route(app, BUTTON_PLAYER_PLAY); return TRUE; case GDK_KEY_Return: control_route(app, BUTTON_PLAYER_CUE); return TRUE; case GDK_KEY_Insert: // omnplay_playlist_item_add(app, 0); return TRUE; case GDK_KEY_Delete: playlist_delete_selected_items(app); return TRUE; case GDK_E: case GDK_e: playlist_item_edit(app); return TRUE; }; return FALSE; }; static gboolean library_tree_button(GtkWidget *widget, GdkEventButton *event, gpointer data) { // g_warning("on_library_grid_button: event->button=%d, event->type=%d", event->button, event->type); if(event->button==1 && event->type==GDK_2BUTTON_PRESS) { playlist_item_add_from_library((instance_t* )data, 0); return TRUE; }; return FALSE; }; static gboolean playlist_grid_button(GtkWidget *widget, GdkEventButton *event, gpointer data) { instance_t* app = (instance_t*)data; // g_warning("on_playlist_grid_button"); if(event->button==1 && event->type==GDK_2BUTTON_PRESS) { playlist_item_edit(app); return TRUE; }; return FALSE; }; static gboolean instance_button_click(instance_t* app, control_buttons_t button) { switch(button) { case BUTTON_PLAYLIST_ITEM_ADD: playlist_item_add(app, 0); break; case BUTTON_PLAYLIST_ITEM_DEL: playlist_delete_selected_items(app); break; case BUTTON_PLAYLIST_ITEM_EDIT: playlist_item_edit(app); break; case BUTTON_PLAYLIST_LOAD: playlist_load(app); break; case BUTTON_PLAYLIST_SAVE: playlist_save(app); break; case BUTTON_PLAYLIST_BLOCK_SINGLE: case BUTTON_PLAYLIST_BLOCK_LOOP: playlist_block(app, (BUTTON_PLAYLIST_BLOCK_LOOP == button)?1:0); break; case BUTTON_PLAYLIST_ITEM_UP: playlist_item_swap(app, -1); break; case BUTTON_PLAYLIST_ITEM_DOWN: playlist_item_swap(app, +1); break; case BUTTON_PLAYER_CUE: case BUTTON_PLAYER_PLAY: case BUTTON_PLAYER_PAUSE: case BUTTON_PLAYER_STOP: control_route(app, button); break; case BUTTON_LIBRARY_ADD: playlist_item_add_from_library(app, 0); break; case BUTTON_LIBRARY_REFRESH: // omnplay_library_refresh(app); break; case BUTTON_LIBRARY_FIND: // omnplay_library_search(app, 0); break; case BUTTON_LIBRARY_FIND_NEXT: // omnplay_library_search(app, 1); break; case BUTTON_PLAYLIST_RELINK: // omnplay_playlist_relink(app); break; default: g_warning("instance_button_click: unknow button clicked"); }; return TRUE; }; static gboolean on_button_click(GtkWidget *button, gpointer user_data) { int i; instance_t* app = (instance_t*)user_data; for(i = 1; i < BUTTON_LAST; i++) if(app->buttons[i] == button) return instance_button_click(app, (control_buttons_t)i); return FALSE; }; static gboolean on_main_window_delete_event( GtkWidget *widget, GdkEvent *event, gpointer user_data ) { g_print ("delete event occurred [start]\n"); gdk_threads_leave(); instance_release((instance_t*)user_data); gdk_threads_enter(); g_print ("delete event occurred [finish]\n"); return FALSE; } static void on_main_window_destroy( GtkWidget *widget, gpointer user_data ) { g_print ("destroy occurred\n"); gtk_main_quit(); } instance_t* instance_create(int argc, char** argv) { int i, c; instance_t* app; /* prepare application instance */ app = (instance_t*)malloc(sizeof(instance_t)); memset(app, 0, sizeof(instance_t)); /* load parameters from command line */ if(!instance_opt(argc, argv, app) && app->players.count) app->window = ui_create(app); else instance_usage(); return app; }; void instance_destroy(instance_t* app) { free(app); }; void instance_init(instance_t* app) { int i; pthread_mutexattr_t attr; #if defined(__MINGW32__) WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); WSAStartup(wVersionRequested, &wsaData); #endif gtk_signal_connect( GTK_OBJECT( app->window ), "delete-event", GTK_SIGNAL_FUNC(on_main_window_delete_event), app); gtk_signal_connect( GTK_OBJECT( app->window ), "destroy", GTK_SIGNAL_FUNC(on_main_window_destroy), app); gtk_widget_add_events(app->playlist_grid, GDK_BUTTON_PRESS_MASK); gtk_widget_add_events(app->playlist_grid, GDK_KEY_PRESS_MASK); gtk_signal_connect(GTK_OBJECT(app->playlist_grid), "key-press-event", GTK_SIGNAL_FUNC(playlist_grid_key), app); gtk_widget_add_events(app->library_tree, GDK_BUTTON_PRESS_MASK); gtk_widget_add_events(app->library_tree, GDK_KEY_PRESS_MASK); gtk_signal_connect(GTK_OBJECT(app->library_tree), "key-press-event", GTK_SIGNAL_FUNC(library_tree_key), app); gtk_signal_connect(GTK_OBJECT(app->playlist_grid), "button-press-event", GTK_SIGNAL_FUNC(playlist_grid_button), app); gtk_signal_connect(GTK_OBJECT(app->library_tree), "button-press-event", GTK_SIGNAL_FUNC(library_tree_button), app); /* create lock */ pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&app->players.lock, &attr); pthread_mutex_init(&app->playlist.lock, &attr); pthread_mutex_init(&app->library.lock, &attr); pthread_mutexattr_destroy(&attr); /* run unit monitoring threads */ for(i = 0; i < app->players.count; i++) player_run(app, i); /* attach buttons click */ for(i = 1; i < BUTTON_LAST; i++) gtk_signal_connect(GTK_OBJECT(app->buttons[i]), "clicked", GTK_SIGNAL_FUNC( on_button_click), app ); /* init library */ library_init(app); /* init playlist */ playlist_init(app); }; void instance_release(instance_t* app) { int i; app->f_exit = 1; /* stop unit monitoring threads */ for(i = 0; i < app->players.count; i++) player_stop(app, i); /* release laylist */ playlist_release(app); /* release library */ library_release(app); /* destroy lock */ pthread_mutex_destroy(&app->players.lock); /* destroy lock */ pthread_mutex_destroy(&app->playlist.lock); /* destroy library lock */ pthread_mutex_destroy(&app->library.lock); };