rendered paste body#include <stdio.h>#include <gtk/gtk.h>#include <gdk/gdkx.h>#include <X11/Xlib.h>#include "playlist.h"#include "notebook/notebook.h"#include "notebook/collection.h"#include "gui.h"#include "playbox.h"#include "statusbox.h"#include "misc.h"#include "coverart_wizard.h"#include "menus.h"#include "audio/audio.h"#include "notify.h"#include "amatory.h"#include "firststart.h"#include "vgtk.h"#include <libgen.h>#include <pthread.h>#ifdef HAVE_LIBNOTIFY#include <libnotify/notify.h>extern NotifyNotification *gnotify;#endifGUI_SESSION gui;#define SETTLE_TIME 15GUI_HOTKEY default_hotkeys[] = { { "z",0,0,on_prev_clicked }, { "x",0,0,on_play_clicked }, { "c",0,0,on_pause_toggled }, { "v",0,0,on_stop_clicked }, { "b",0,0,on_next_clicked }, {NULL}};static void on_quit(GtkWidget *widget, gpointer data){ GUI_SESSION *g = data; printf("quit button says bye\n"); /* Save playlist */ playlist_save_session(); gtk_main_quit(); g->amatory->audio_session->AUDIO_stop(g->amatory->audio_session); AMATORY_shutdown(g->amatory);#ifdef HAVE_LIBNOTIFY notify_notification_close(gnotify,NULL); notify_uninit ();#endif /* just to make valgrind happier */ //g_object_unref(g->collection_filter);// gtk_tree_path_free(g->active_path);}static gboolean on_gui_configure_event(GtkWidget *window, GdkEventConfigure *event, GtkWidget *box){ gint h=0,w=0; if(event->type == GDK_CONFIGURE){ gdk_window_get_geometry(window->window,NULL,NULL,&w,&h,NULL); gtk_widget_set_size_request (box,w,h); } return FALSE;}int CM_event_id = 0;static gboolean collection_change_done(gpointer data){ printf("Collection Changes are DONE!\n"); LIBRARY_factor_VA(); repopulate_collection(); CM_event_id = 0; return FALSE;}static void on_collection_change(GFileMonitor *monitor,GFile *file,GFile *other_file, GFileMonitorEvent event_type,gpointer user_data){ char *path=NULL; char *base = NULL, *dir = NULL; path = g_file_get_path(file); printf("collection_monitor: %s\n",path); switch(event_type){ case G_FILE_MONITOR_EVENT_CHANGED: printf("CM: Ignoring EVENT CHANGED\n"); /* Ignore printf("CM: Changed\n"); */ break; case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: base = strdup(basename(path)); free(path); path = g_file_get_path(file); dir = strdup(dirname(path)); printf("CM: Change Done: dir=%s,base=%s\n",dir,base); LIBRARY_update_file(gui.amatory->audio_session,dir,base); if(CM_event_id == 0){ CM_event_id = gdk_threads_add_timeout_seconds(SETTLE_TIME, collection_change_done,NULL); }else{ g_source_remove(CM_event_id); CM_event_id = gdk_threads_add_timeout_seconds(SETTLE_TIME, collection_change_done,NULL); } break; case G_FILE_MONITOR_EVENT_DELETED: printf("CM: Deleted\n"); if(g_file_query_file_type(file,G_FILE_QUERY_INFO_NONE,NULL) != G_FILE_TYPE_DIRECTORY){ base = strdup(basename(path)); free(path); path = g_file_get_path(file); dir = strdup(dirname(path)); LIBRARY_delete_tag(dir,base); }else{ g_file_monitor_cancel(monitor); LIBRARY_delete_tag(path,NULL); } break; case G_FILE_MONITOR_EVENT_CREATED: printf("CM: Created\n"); if(g_file_query_file_type(file,G_FILE_QUERY_INFO_NONE,NULL) == G_FILE_TYPE_DIRECTORY){ printf("CM: Adding new file monitor directory\n"); vg_file_monitor_directory(path, on_collection_change); LIBRARY_quick_dir_scanfs(gui.amatory->audio_session,path); if(CM_event_id == 0){ CM_event_id = gdk_threads_add_timeout_seconds(SETTLE_TIME, collection_change_done,NULL); }else{ g_source_remove(CM_event_id); CM_event_id = gdk_threads_add_timeout_seconds(SETTLE_TIME, collection_change_done,NULL); } } break; case G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED: printf("CM: Ignoring Attribute Changed\n"); /* Ignore printf("CM: Attribute Changed\n"); */ break; default: printf("Unahndled event = %i\n",event_type); } g_free(path);}static void *deploy_file_monitors(void *args){ char **paths= NULL; long long size; int i; size = LIBRARY_get_paths(&paths); for(i=0;i<size;i++){ printf("deploy_file_monitors: Start: %i=%s\n",i,paths[i]);// gdk_threads_enter(); vg_file_monitor_directory(paths[i],on_collection_change);// gdk_threads_leave(); printf("deploy_file_monitors: Done: %i=%s\n",i,paths[i]); } HELPER_free_array((void **)paths,0,free); return NULL;}static void *global_key_press(void *arg){ Display *d = NULL; Window w; XEvent e; XModifierKeymap *modmap; int i; int key=0; int rv; unsigned int super_mask = 0; printf("global_key_press:\n"); d = XOpenDisplay(NULL); w = DefaultRootWindow(d); /* modmap = XGetModifierMapping(d); int j; for(i=0;i<8;i++){ for(j=0;j<modmap->max_keypermod;j++){ if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(d, XK_Control_L )){ super_mask = 1<<i; } } } XFreeModifiermap(modmap);// printf("XK_Super_L = %x\n",super_mask);*/ // Mod4Mask == Super key apparently // 0x1c = Shift+Super // 0x40 = Super or 0x50, why does it keep changing? for(i=0;default_hotkeys[i].key_string;i++){ key = XKeysymToKeycode(d, XStringToKeysym(default_hotkeys[i].key_string)); rv = XGrabKey(d,key,0x50,w,True,GrabModeAsync,GrabModeAsync); rv = XGrabKey(d,key,0x40,w,True,GrabModeAsync,GrabModeAsync); if(rv == BadAccess){ printf("XGrabKey: BadAccess - %s\n", default_hotkeys[i].key_string); }else if(rv == BadValue){ printf("XGrabKey: BadValue - %s\n", default_hotkeys[i].key_string); }else if(rv == BadWindow){ printf("XGrabKey: BadWindow\n"); } default_hotkeys[i].key = key; } XSync (d,0); // Gtk segfaults without this for(;;){ printf("while_ global_key_press:\n"); XNextEvent(d, &e); if(e.type == KeyPress){ for(i=0;default_hotkeys[i].key_string;i++){ if(default_hotkeys[i].key == e.xkey.keycode){ gdk_threads_enter(); default_hotkeys[i].callback(NULL,NULL); gdk_threads_leave(); } } printf("key=0x%x\n",key); printf("state=0x%x\n",e.xkey.state); } } return NULL;}int main(int argc, char **argv){ GtkWidget *window; GtkWidget *main_window_box; GtkPaned *main_window_pane; GtkWidget *main_notebook; GtkWidget *playlist_pane_vbox; GtkWidget *status_bar; GtkWidget *playbox; GtkWidget *main_window_layout; GtkTreeView *playlist_view; GtkWidget *scroll_playlist_window; GdkPixbuf *pixbuf; pthread_t tid,key_press_tid; char *user,*pass; GdkGeometry gdkGeometry; gui.scale_flag=0; gui.last_playing = NULL; gui.lastfm_handler_id = 0; gui.scale_handler_id = 0; gui.playing = NULL; gui.active_row = NULL; /* startup the backend */ if(AMATORY_get_credentials(&user,&pass)){ printf("Login information unavailable. Starting wizard...\n"); do_firststart_wizard(argc,argv); exit(0); }else{ gui.amatory = AMATORY_startup(user,pass,"mysql","Amatory"); if(gui.amatory == NULL){ printf("Could not start Amatory\n"); exit(1); } } free(user);free(pass); /* Secure glib */ if( ! g_thread_supported() ) g_thread_init( NULL ); /* Secure gtk */ gdk_threads_init(); gdk_threads_enter(); gtk_init(&argc,&argv);#ifdef HAVE_LIBNOTIFY notify_init("Amatory Media Player"); gnotify = notify_notification_new("Amatory Media Player", "Version 0.1",NULL,NULL); notify_notification_show(gnotify,NULL);#endif /* Create the top level window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gui.window = window; pixbuf = gdk_pixbuf_new_from_file_at_size( "/usr/share/Amatory/amatory-logo.svg", ARTIST_BUTTON_WIDTH,-1,NULL); gtk_window_set_icon(GTK_WINDOW(window),pixbuf); g_object_unref(pixbuf); gdkGeometry.min_width= 800; gdkGeometry.min_height = 600; gtk_window_set_geometry_hints(GTK_WINDOW(window), window, &gdkGeometry, GDK_HINT_MIN_SIZE); gtk_widget_realize (window); /* Everything starts off with a GtkLayout */ main_window_layout = gtk_layout_new(NULL,NULL); gtk_container_add(GTK_CONTAINER(window),main_window_layout); /* But the entire app is built using boxes, the GtkLayout is only * needed to get the overlapping notificcation window */ /* (Homogeneous, Spacing) */ main_window_box = gtk_vbox_new(FALSE, 0); /* Add the vertical box to the layout */ gtk_container_add(GTK_CONTAINER(main_window_layout),main_window_box); g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (on_quit), &gui); g_signal_connect(G_OBJECT(window),"configure-event", G_CALLBACK(on_gui_configure_event),main_window_box);// g_signal_connect (G_OBJECT(window),"key-press-event",// G_CALLBACK(on_main_key_press_event),NULL); /* Add a horizontal pane to the main window */ main_window_pane = GTK_PANED(gtk_hpaned_new()); gtk_box_pack_start(GTK_BOX(main_window_box), GTK_WIDGET(main_window_pane),TRUE,TRUE,0); gtk_paned_set_position(main_window_pane,325); /* Deploy all the file monitors */ pthread_create(&tid,NULL,deploy_file_monitors,NULL); playlist_pane_vbox = gtk_vbox_new(FALSE,0); /* Create the playlist window */ scroll_playlist_window = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll_playlist_window), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW (scroll_playlist_window), GTK_POLICY_NEVER,GTK_POLICY_AUTOMATIC); /* Add the playlist window to the right hand side of the pane */ gtk_box_pack_start(GTK_BOX(playlist_pane_vbox),scroll_playlist_window, TRUE,TRUE,0); playbox = create_playbox(); gtk_box_pack_start(GTK_BOX(playlist_pane_vbox),playbox,FALSE,FALSE,0); gtk_paned_add2(GTK_PANED(main_window_pane), playlist_pane_vbox); /* Create the playlist */ playlist_view = create_playlist(); gtk_container_add(GTK_CONTAINER(scroll_playlist_window), GTK_WIDGET(playlist_view)); /* Add a status bar to the bottom of the main window */ status_bar = create_statusbox(); /* Expand = False, Fill = True, Padding = 0 */ gtk_box_pack_end(GTK_BOX(main_window_box),status_bar, FALSE, TRUE, 0); /* Add a notebook to the left side of the pane */ main_notebook = create_notebook(); gtk_paned_add1(GTK_PANED(main_window_pane), main_notebook); gui.notify_view = initialise_notifier(); gtk_widget_show_all(window); gdk_window_set_keep_above(gui.notify_view->window,TRUE);// gdk_window_set_keep_below(gui.content_view->window,TRUE); g_signal_connect(main_notebook,"switch-page", G_CALLBACK(on_switch_page),NULL); pthread_create(&key_press_tid,NULL,global_key_press,NULL); gtk_main(); printf("After Main\n"); gdk_threads_leave(); return 0;}