📄 xlyrics.c
字号:
/* XLyrics by xiaosuo <xiaosuo1@eyou.com> * Homepage gentux.blogchina.com * * 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. */#include<gtk/gtk.h>#include<gdk/gdk.h>#include<gdk/gdkx.h>#include<glib.h>#include<gmodule.h>#include<locale.h>#include <X11/Xlib.h>#include <X11/Xatom.h>#define OPAQUE 0xffffffff#include"xlyrics.h"#include"lyrics.h"#include"find.h"#include"conf.h"#include"lyrics_download.h"#include"internal.h"struct Song *song = NULL; /*current song name*/struct LyricsLine *lyrics_line = NULL; /*currnet line of lyrics*//*****the configure*/gint width=390, height=500; /* the main window width and height*/gint pos_x=200, pos_y=400; /* the window position*/GdkColor bg_color = {0, 0, 0, 0}; /*back ground color*/GdkColor ac_color = {0, 0xffff, 0xffff, 0}; /*activated font color*/GdkColor ua_color = {0, 0, 0, 0xffff}; /*unactivated font color*/gchar lyrics_font[32] = "Sans 16"; /*font used for display the lyrics*/gchar lyrics_dir[255] = ""; /*directory store the lyrics*/gchar plugin_name[255] = ""; /* the plugin name*/gboolean look_in_mp3dir_mode = FALSE; /*look up in mp3 dir or not*/gboolean is_keep_above = FALSE; /*make window keep above or not*/gboolean have_border = FALSE; /*make window have border or not*/gboolean is_fit_width = FALSE; /*automatic change the the widget width*/gboolean hide_not_found = FALSE; /*hide if not found any lyrics*/guint opacity; /*the window's opacity*//*****************/gboolean is_config_update = FALSE;gboolean hiding = FALSE;GtkWidget *window = NULL; /* main window*/GtkListStore *list_store = NULL; /*the list of the lyrics lines*/GtkWidget *list_view = NULL; /* used to show the list_store*/GtkWidget *scrolled_window = NULL; /* the scrolled window */GtkCellRenderer *cell = NULL; /*the render of the cell*/gchar last_song[255] = ""; /*the last song name*/gint last_line_number = 0; /* record the line number*/gchar lyrics_file[255] = ""; /*current lyrics file name */char *playfile; /* the current mp3 name */gchar mp3_dir[255] = ""; /* the mp3 dir path*/gboolean is_lyrics_loaded = FALSE; /* the lyrics file loaded or not*/typedef int (*is_players_on) (void);typedef int (*launch_players) (void);typedef char* (*get_players_song) (int session);typedef int (*get_players_time) (int session);typedef int (*set_players_time) (int session, int time);GModule *module; /*the plugin module*/int timer; /*the timer*/int session; /*the current player session*/int is_downloading = 0; /*downloading lyrics*/is_players_on is_player_on; /*if player on or not*/launch_players launch_player; /*launch a new player session*/get_players_song get_player_song; /*get the current song name*/get_players_time get_player_time; /*get the current song time*/set_players_time set_player_time; /*set the current song time*/typedefstruct Position{ gdouble x; gdouble y;} Position;Position mouse_position={0,0};gboolean is_left_button_pressed = FALSE;gboolean is_window_resized = FALSE;void load_lyrics_file(char *playfile_full);/* set the widget's transparency to opacity * opacity is guint 0x00000000-0xffffffff */int my_gtk_widget_set_transparency(GtkWidget *widget, guint opacity){ Display *display; Window window; Window parent_win; Window root_win; Window* child_windows; int num_child_windows; if(!GTK_IS_WIDGET(widget)){ printf("gtk_widget_set_transparency: not a widget!\n"); abort(); } /* map the widget */ gtk_widget_show(widget); /* Set the Display and Screen */ display = (Display*)gdk_x11_get_default_xdisplay(); /* sync, so the window manager can know the new widget */ XSync(display, False); window = GDK_WINDOW_XWINDOW(widget->window); /* Get the cureent window's top-level window */ while(1){ XQueryTree(display, window, &root_win, &parent_win, &child_windows, &num_child_windows); XFree(child_windows); /* found the top-level window */ if(root_win == parent_win) break; window = parent_win; } if(opacity == OPAQUE){ XDeleteProperty(display, window, XInternAtom(display, "_KDE_WM_WINDOW_OPACITY", False)); XDeleteProperty(display, window, XInternAtom(display, "_NET_WM_WINDOW_OPACITY", False)); }else{ XChangeProperty(display, window, XInternAtom(display, "_KDE_WM_WINDOW_OPACITY", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L); XChangeProperty(display, window, XInternAtom(display, "_NET_WM_WINDOW_OPACITY", False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &opacity, 1L); } XSync(display, False); return 0;}/*exit the lyrics and save the current posion ,width, height*/void quit(GtkWidget *widget, gpointer data){ update_config("xlyrics"); gtk_list_store_clear(list_store); lyrics_cleanup(song); song = NULL; g_source_remove(timer); g_module_close(module); gtk_main_quit();}/*keep above or not*/void keep_above(void){ is_keep_above = !is_keep_above; gtk_window_set_keep_above(GTK_WINDOW(window), is_keep_above);}/*have border or not*/void no_border(void){ have_border = !have_border; gtk_window_set_decorated(GTK_WINDOW(window), have_border);}/*fit width or not*/void fit_width(void){ is_fit_width = !is_fit_width; if(is_fit_width){ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); }else{ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS); gtk_window_resize(GTK_WINDOW(window), width, height); }}/*move or resize the main window with the mouse*/gboolean move_with_mouse(GtkWidget *widget, GdkEventMotion *event){ gint x, y; if(is_left_button_pressed) { x = pos_x + (event->x_root - mouse_position.x); y = pos_y + (event->y_root - mouse_position.y); if( x != pos_x || y != pos_y) gtk_window_move(GTK_WINDOW(window), x, y); } if(is_window_resized) { gtk_window_resize(GTK_WINDOW(window), event->x, event->y); } return FALSE;}/*deal with the left button released*/gboolean left_button_released(GtkWidget *widget, GdkEventButton *event){ if (event->button == 1) { is_left_button_pressed = FALSE; is_window_resized = FALSE; gdk_window_set_cursor(event->window, gdk_cursor_new(GDK_LEFT_PTR)); gtk_window_get_position(GTK_WINDOW(window), &pos_x, &pos_y); gtk_window_get_size(GTK_WINDOW(window), &width, &height); } return FALSE; }/* manual download current music's lyrics */void manual_download(void){ if(is_lyrics_loaded) unlink(lyrics_file); is_downloading = 0; load_lyrics_file(get_player_song(session));};/*popup menu*/void popup_menu(GtkWidget *widget, GdkEventButton *event){ GtkWidget *menu; GtkWidget *item; gint button, event_time; menu = gtk_menu_new (); /* ... add menu items ... */ item = gtk_check_menu_item_new_with_label(_("Keep above ")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), is_keep_above); g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(keep_above), NULL ); item = gtk_check_menu_item_new_with_label(_("No border")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), !have_border); g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(no_border), NULL ); item = gtk_check_menu_item_new_with_label(_("Auto adjust width")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), is_fit_width); g_signal_connect(G_OBJECT(item), "toggled", G_CALLBACK(fit_width), NULL ); item = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); item = gtk_menu_item_new_with_label(_("Download this lyrics")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(manual_download), NULL); item = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); item = gtk_menu_item_new_with_label(_("Interface config")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(config), (gpointer)0); item = gtk_menu_item_new_with_label(_("Generally config")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(config), (gpointer)1); item = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); item = gtk_menu_item_new_with_label(_("About")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(config), (gpointer)2); item = gtk_menu_item_new_with_label(_("Exit")); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(quit), "pop"); gtk_widget_show_all(menu); if (event) { button = event->button; event_time = event->time; } else { button = 0; event_time = gtk_get_current_event_time (); } gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, button, event_time);}/* deal withe mouse event*/gboolean deal_with_mouse(GtkWidget *widget, GdkEventButton *event){ if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { popup_menu (widget, event); } if (event->button == 1 && event->type == GDK_BUTTON_PRESS) { if(event->x < width - 5 ||event->y < height - 5) { is_left_button_pressed = TRUE; gdk_window_set_cursor(event->window, gdk_cursor_new(GDK_FLEUR)); mouse_position.x = event->x_root; mouse_position.y = event->y_root; gtk_window_get_position(GTK_WINDOW(window), &pos_x, &pos_y); } else { is_window_resized = TRUE; gdk_window_set_cursor(event->window, gdk_cursor_new(GDK_BOTTOM_RIGHT_CORNER)); } } return FALSE; }/* init the plugin for xlyrics*/gboolean init_plugin(gchar *plugin_name){ gchar full_plugin_name[1024]; if(g_module_supported()) { snprintf(full_plugin_name, 1024, "%s/%s", PACKAGE_LIB_DIR, plugin_name); module = g_module_open(full_plugin_name, G_MODULE_BIND_LAZY); if(module == NULL){ printf("error while openning module: %s\n", full_plugin_name); printf("\t %s\n", g_module_error()); return FALSE; } if(g_module_symbol(module, "is_on", (gpointer*)&is_player_on) && g_module_symbol(module, "launch", (gpointer*)&launch_player) && g_module_symbol(module, "get_song", (gpointer*)&get_player_song) && g_module_symbol(module, "get_time", (gpointer*)&get_player_time) && g_module_symbol(module, "set_time", (gpointer*)&set_player_time)) return TRUE; return FALSE; } else { printf("gmodule is not supported\n"); exit(-1); }}/*set a line activated or not*/void set_line(gint row, gboolean stat){ GtkTreeIter iter; GtkTreePath *path; /*if overflow*/ if(row >= gtk_tree_model_iter_n_children(GTK_TREE_MODEL(list_store), NULL)) return; gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(list_store), &iter, NULL, row); gtk_list_store_set(list_store, &iter, 1, stat, -1); if(stat == FALSE) return; /* if active scroll to the row*/ path = gtk_tree_model_get_path(GTK_TREE_MODEL(list_store), &iter); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(list_view), path, NULL, TRUE, 0.5, 0.5); gtk_tree_path_free(path);}/*read lyrics and fill the list_store*/void read_lyrics(char *file_name){ GtkTreeIter iter; if(!strcmp(file_name, "")) return; if(!is_lyrics_loaded) { gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, 0, file_name, 1, FALSE, 2, 0, -1); return; } song = read_lyrics_file(file_name); for(lyrics_line = song->head; lyrics_line != NULL; lyrics_line = lyrics_line->next) { gtk_list_store_append (GTK_LIST_STORE (list_store), &iter); gtk_list_store_set (GTK_LIST_STORE (list_store), &iter, 0, lyrics_line->buffer, 1, FALSE, 2, lyrics_line->line_number, -1); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -