⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 song_change.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
字号:
#include "config.h"#include "xmms/i18n.h"#include <gtk/gtk.h>#include <sys/types.h>#include <sys/wait.h>#include <signal.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include "xmms/plugin.h"#include "libxmms/configfile.h"#include "libxmms/xmmsctrl.h"#include "libxmms/formatter.h"static void init(void);static void cleanup(void);static void configure(void);static gint timeout_func(gpointer);static gint timeout_tag = 0;static gint previous_song = -1;static gchar *cmd_line = NULL;static gboolean possible_pl_end;static gchar *cmd_line_end;static GtkWidget *configure_win = NULL, *configure_vbox;static GtkWidget *cmd_entry, *cmd_end_entry;GeneralPlugin sc_gp ={	NULL,			/* handle */	NULL,			/* filename */	-1,			/* xmms_session */	NULL,			/* Description */	init,	NULL,	configure,	cleanup,};GeneralPlugin *get_gplugin_info(void){	sc_gp.description = g_strdup_printf(_("Song Change %s"), VERSION);	return &sc_gp;}static void read_config(void){	ConfigFile *cfgfile;	g_free(cmd_line);	g_free(cmd_line_end);	cmd_line = NULL;	cmd_line_end = NULL;	if ((cfgfile = xmms_cfg_open_default_file()) != NULL)	{		xmms_cfg_read_string(cfgfile, "song_change", "cmd_line", &cmd_line);		xmms_cfg_read_string(cfgfile, "song_change", "cmd_line_end", &cmd_line_end);		xmms_cfg_free(cfgfile);	}}static void init(void){	read_config();	previous_song = -1;	timeout_tag = gtk_timeout_add(100, timeout_func, NULL);}static void cleanup(void){	if (timeout_tag)		gtk_timeout_remove(timeout_tag);	timeout_tag = 0;	if (cmd_line)		g_free(cmd_line);	if (cmd_line_end)		g_free(cmd_line_end);	cmd_line = NULL;	cmd_line_end = NULL;	signal(SIGCHLD, SIG_DFL);}static void save_and_close(GtkWidget *w, gpointer data){	char *cmd, *cmd_end;	ConfigFile *cfgfile = xmms_cfg_open_default_file();	cmd = gtk_entry_get_text(GTK_ENTRY(cmd_entry));	cmd_end = gtk_entry_get_text(GTK_ENTRY(cmd_end_entry));	xmms_cfg_write_string(cfgfile, "song_change", "cmd_line", cmd);	xmms_cfg_write_string(cfgfile, "song_change", "cmd_line_end", cmd_end);	xmms_cfg_write_default_file(cfgfile);	xmms_cfg_free(cfgfile);	if (timeout_tag)	{		g_free(cmd_line);		cmd_line = g_strdup(cmd);		g_free(cmd_line_end);		cmd_line_end = g_strdup(cmd_end);	}	gtk_widget_destroy(configure_win);}static void warn_user(void){	GtkWidget *warn_win, *warn_vbox, *warn_desc;	GtkWidget *warn_bbox, *warn_yes, *warn_no;	warn_win = gtk_window_new(GTK_WINDOW_DIALOG);	gtk_window_set_title(GTK_WINDOW(warn_win), _("Warning"));	gtk_window_set_transient_for(GTK_WINDOW(warn_win),				     GTK_WINDOW(configure_win));	gtk_window_set_modal(GTK_WINDOW(warn_win), TRUE);		gtk_container_set_border_width(GTK_CONTAINER(warn_win), 10);	warn_vbox = gtk_vbox_new(FALSE, 10);	gtk_container_add(GTK_CONTAINER(warn_win), warn_vbox);	warn_desc = gtk_label_new(_(		"Filename and song title tags should be inside "		"double quotes (\").  Not doing so might be a "		"security risk.  Continue anyway?"));	gtk_label_set_justify(GTK_LABEL(warn_desc), GTK_JUSTIFY_LEFT);	gtk_misc_set_alignment(GTK_MISC(warn_desc), 0, 0.5);	gtk_box_pack_start(GTK_BOX(warn_vbox), warn_desc, FALSE, FALSE, 0);	gtk_label_set_line_wrap(GTK_LABEL(warn_desc), TRUE);					  	warn_bbox = gtk_hbutton_box_new();	gtk_button_box_set_layout(GTK_BUTTON_BOX(warn_bbox), GTK_BUTTONBOX_END);	gtk_button_box_set_spacing(GTK_BUTTON_BOX(warn_bbox), 5);	gtk_box_pack_start(GTK_BOX(warn_vbox), warn_bbox, FALSE, FALSE, 0);	warn_yes = gtk_button_new_with_label(_("Yes"));	gtk_signal_connect(GTK_OBJECT(warn_yes), "clicked",			   GTK_SIGNAL_FUNC(save_and_close), NULL);	gtk_signal_connect_object(GTK_OBJECT(warn_yes), "clicked",				  GTK_SIGNAL_FUNC(gtk_widget_destroy),				  GTK_OBJECT(warn_win));	GTK_WIDGET_SET_FLAGS(warn_yes, GTK_CAN_DEFAULT);	gtk_box_pack_start(GTK_BOX(warn_bbox), warn_yes, TRUE, TRUE, 0);	gtk_widget_grab_default(warn_yes);	warn_no = gtk_button_new_with_label(_("No"));	gtk_signal_connect_object(GTK_OBJECT(warn_no), "clicked",				  GTK_SIGNAL_FUNC(gtk_widget_destroy),				  GTK_OBJECT(warn_win));	GTK_WIDGET_SET_FLAGS(warn_no, GTK_CAN_DEFAULT);	gtk_box_pack_start(GTK_BOX(warn_bbox), warn_no, TRUE, TRUE, 0);	gtk_widget_show_all(warn_win);}static int check_command(char *command){	const char *dangerous = "fns";	char *c;	int qu = 0;		for (c = command; *c != '\0'; c++)	{		if (*c == '"' && (c == command || *(c - 1) != '\\'))			qu = !qu;		else if (*c == '%' && !qu && strchr(dangerous, *(c + 1)))			return -1;	}	return 0;}static void configure_ok_cb(GtkWidget *w, gpointer data){	char *cmd, *cmd_end;	cmd = gtk_entry_get_text(GTK_ENTRY(cmd_entry));	cmd_end = gtk_entry_get_text(GTK_ENTRY(cmd_end_entry));	if (check_command(cmd) < 0 || check_command(cmd_end) < 0)		warn_user();	else		save_and_close(NULL, NULL);}static void configure(void){	GtkWidget *cmd_hbox, *cmd_label, *cmd_end_hbox, *cmd_end_label;	GtkWidget *song_desc, *end_desc;	GtkWidget *configure_bbox, *configure_ok, *configure_cancel;	GtkWidget *song_frame, *song_vbox, *end_frame, *end_vbox;	gchar *temp;		if (configure_win)		return;	read_config();	configure_win = gtk_window_new(GTK_WINDOW_DIALOG);	gtk_signal_connect(GTK_OBJECT(configure_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &configure_win);	gtk_window_set_title(GTK_WINDOW(configure_win), _("Song Change Configuration"));		gtk_container_set_border_width(GTK_CONTAINER(configure_win), 10);	configure_vbox = gtk_vbox_new(FALSE, 10);	gtk_container_add(GTK_CONTAINER(configure_win), configure_vbox);	song_frame = gtk_frame_new(_("Song change"));	gtk_box_pack_start(GTK_BOX(configure_vbox), song_frame, FALSE, FALSE, 0);	song_vbox = gtk_vbox_new(FALSE, 10);	gtk_container_set_border_width(GTK_CONTAINER(song_vbox), 5);	gtk_container_add(GTK_CONTAINER(song_frame), song_vbox);		end_frame = gtk_frame_new(_("Playlist end"));	gtk_box_pack_start(GTK_BOX(configure_vbox), end_frame, FALSE, FALSE, 0);	end_vbox = gtk_vbox_new(FALSE, 10);	gtk_container_set_border_width(GTK_CONTAINER(end_vbox), 5);	gtk_container_add(GTK_CONTAINER(end_frame), end_vbox);		temp = g_strdup_printf(_(		"Shell-command to run when xmms changes song.  "		"It can optionally include the string %%s which will be "		"replaced by the new song title."));	song_desc = gtk_label_new(temp);	g_free(temp);	gtk_label_set_justify(GTK_LABEL(song_desc), GTK_JUSTIFY_LEFT);	gtk_misc_set_alignment(GTK_MISC(song_desc), 0, 0.5);	gtk_box_pack_start(GTK_BOX(song_vbox), song_desc, FALSE, FALSE, 0);	gtk_label_set_line_wrap(GTK_LABEL(song_desc), TRUE);					  	cmd_hbox = gtk_hbox_new(FALSE, 5);	gtk_box_pack_start(GTK_BOX(song_vbox), cmd_hbox, FALSE, FALSE, 0);	cmd_label = gtk_label_new(_("Command:"));	gtk_box_pack_start(GTK_BOX(cmd_hbox), cmd_label, FALSE, FALSE, 0);	cmd_entry = gtk_entry_new();	if (cmd_line)		gtk_entry_set_text(GTK_ENTRY(cmd_entry), cmd_line);	gtk_widget_set_usize(cmd_entry, 200, -1);	gtk_box_pack_start(GTK_BOX(cmd_hbox), cmd_entry, TRUE, TRUE, 0);	end_desc = gtk_label_new(_(		"Shell-command to run when xmms reaches the end "		"of the playlist."));	gtk_label_set_justify(GTK_LABEL(end_desc), GTK_JUSTIFY_LEFT);	gtk_misc_set_alignment(GTK_MISC(end_desc), 0, 0.5);	gtk_box_pack_start(GTK_BOX(end_vbox), end_desc, FALSE, FALSE, 0);	gtk_label_set_line_wrap(GTK_LABEL(end_desc), TRUE);					  	cmd_end_hbox = gtk_hbox_new(FALSE, 5);	gtk_box_pack_start(GTK_BOX(end_vbox), cmd_end_hbox, FALSE, FALSE, 0);	cmd_end_label = gtk_label_new(_("Command:"));	gtk_box_pack_start(GTK_BOX(cmd_end_hbox), cmd_end_label, FALSE, FALSE, 0);	cmd_end_entry = gtk_entry_new();	if (cmd_line_end)		gtk_entry_set_text(GTK_ENTRY(cmd_end_entry), cmd_line_end);	gtk_widget_set_usize(cmd_end_entry, 200, -1);	gtk_box_pack_start(GTK_BOX(cmd_end_hbox), cmd_end_entry, TRUE, TRUE, 0);	configure_bbox = gtk_hbutton_box_new();	gtk_button_box_set_layout(GTK_BUTTON_BOX(configure_bbox), GTK_BUTTONBOX_END);	gtk_button_box_set_spacing(GTK_BUTTON_BOX(configure_bbox), 5);	gtk_box_pack_start(GTK_BOX(configure_vbox), configure_bbox, FALSE, FALSE, 0);	configure_ok = gtk_button_new_with_label(_("Ok"));	gtk_signal_connect(GTK_OBJECT(configure_ok), "clicked", GTK_SIGNAL_FUNC(configure_ok_cb), NULL);	GTK_WIDGET_SET_FLAGS(configure_ok, GTK_CAN_DEFAULT);	gtk_box_pack_start(GTK_BOX(configure_bbox), configure_ok, TRUE, TRUE, 0);	gtk_widget_grab_default(configure_ok);	configure_cancel = gtk_button_new_with_label(_("Cancel"));	gtk_signal_connect_object(GTK_OBJECT(configure_cancel), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(configure_win));	GTK_WIDGET_SET_FLAGS(configure_cancel, GTK_CAN_DEFAULT);	gtk_box_pack_start(GTK_BOX(configure_bbox), configure_cancel, TRUE, TRUE, 0);	gtk_widget_show_all(configure_win);}static void bury_child(int signal){	waitpid(-1, NULL, WNOHANG);}static void execute_command(gchar *cmd){	gchar *argv[4] = {"/bin/sh", "-c", NULL, NULL};	gint i;	argv[2] = cmd;	signal(SIGCHLD, bury_child);	if (fork() == 0)	{		/* We don't want this process to hog the audio device etc */		for (i = 3; i < 255; i++)			close(i);		execv("/bin/sh", argv);	}}/* * escape_shell_chars() * * Escapes characters that are special to the shell inside double quotes. */static char * escape_shell_chars(char * string){	const gchar *special = "$`\"\\"; /* Characters to escape */	char *in = string, *out;	char *escaped;	int num = 0;	while (*in != '\0')		if (strchr(special, *in++))			num++;	escaped = g_malloc(strlen(string) + num + 1);	in = string;	out = escaped;	while (*in != '\0')	{		if (strchr(special, *in))			*out++ = '\\';		*out++ = *in++;	}	*out = '\0';	return escaped;}static gint timeout_func(gpointer data){	int pos, length, rate, freq, nch;	char *str, *shstring = NULL, *temp, numbuf[16];	gboolean playing, run_end_cmd = FALSE;	static char *previous_file;	char *current_file;	Formatter *formatter;	GDK_THREADS_ENTER();	playing = xmms_remote_is_playing(sc_gp.xmms_session);	pos = xmms_remote_get_playlist_pos(sc_gp.xmms_session);	current_file = xmms_remote_get_playlist_file(sc_gp.xmms_session, pos);		/* Format codes:	 *	 *   F - frequency (in hertz)	 *   c - number of channels	 *   f - filename (full path)	 *   l - length (in milliseconds)	 *   n - name	 *   r - rate (in bits per second)	 *   s - name (since everyone's used to it)	 *   t - playlist position (%02d)	 */	if (pos != previous_song ||	    (!previous_file && current_file) ||	    (previous_file && !current_file) ||	    (previous_file && current_file &&	     strcmp(previous_file, current_file)))	{		g_free(previous_file);		previous_file = current_file;		current_file = NULL;		previous_song = pos;		if (cmd_line && strlen(cmd_line) > 0)		{			formatter = xmms_formatter_new();			str = xmms_remote_get_playlist_title(sc_gp.xmms_session, pos);			if (str)			{				temp = escape_shell_chars(str);				xmms_formatter_associate(formatter, 's', temp);				xmms_formatter_associate(formatter, 'n', temp);				g_free(str);				g_free(temp);			}			else			{				xmms_formatter_associate(formatter, 's', "");				xmms_formatter_associate(formatter, 'n', "");			}                               			if (previous_file)			{				temp = escape_shell_chars(previous_file);				xmms_formatter_associate(formatter, 'f', temp);				g_free(temp);			}			else				xmms_formatter_associate(formatter, 'f', "");			sprintf(numbuf, "%02d", pos + 1);			xmms_formatter_associate(formatter, 't', numbuf);			length = xmms_remote_get_playlist_time(sc_gp.xmms_session, pos);			if (length != -1)			{				sprintf(numbuf, "%d", length);				xmms_formatter_associate(formatter, 'l', numbuf);			}			else				xmms_formatter_associate(formatter, 'l', "0");			xmms_remote_get_info(sc_gp.xmms_session, &rate, &freq, &nch);			sprintf(numbuf, "%d", rate);			xmms_formatter_associate(formatter, 'r', numbuf);			sprintf(numbuf, "%d", freq);			xmms_formatter_associate(formatter, 'F', numbuf);			sprintf(numbuf, "%d", nch);			xmms_formatter_associate(formatter, 'c', numbuf);			shstring = xmms_formatter_format(formatter, cmd_line);			xmms_formatter_destroy(formatter);		}	}	g_free(current_file);	if (playing)	{		int playlist_length = xmms_remote_get_playlist_length(sc_gp.xmms_session);		if (pos + 1 == playlist_length)			possible_pl_end = TRUE;		else			possible_pl_end = FALSE;	}	else if (possible_pl_end)	{		if (pos == 0 && cmd_line_end && strlen(cmd_line_end) > 0)			run_end_cmd = TRUE;		possible_pl_end = FALSE;	}	if (shstring)	{		execute_command(shstring);		g_free(shstring); /* FIXME: This can possibly be freed too early */	}	if (run_end_cmd)		execute_command(cmd_line_end);	GDK_THREADS_LEAVE();	return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -