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

📄 playlist.c

📁 Aqualung is an advanced music player primarily targeted for the GNU/Linux operating system, but als
💻 C
📖 第 1 页 / 共 5 页
字号:
/*                                                     -*- linux-c -*-    Copyright (C) 2004 Tom Szilagyi    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., 675 Mass Ave, Cambridge, MA 02139, USA.    $Id: playlist.c,v 1.116 2006/09/23 14:27:26 pasp Exp $*/#include <config.h>#include <stdio.h>#include <string.h>#include <dirent.h>#include <unistd.h>#include <sys/stat.h>#include <math.h>#include <gtk/gtk.h>#include <gdk/gdkkeysyms.h>#include <glib.h>#include <glib/gstdio.h>#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include "common.h"#include "core.h"#include "rb.h"#include "gui_main.h"#include "music_browser.h"#include "file_info.h"#include "decoder/dec_mod.h"#include "decoder/file_decoder.h"#include "meta_decoder.h"#include "volume.h"#include "options.h"#include "i18n.h"#include "search_playlist.h"#include "playlist.h"#include "ifp_device.h"extern options_t options;extern void assign_audio_fc_filters(GtkFileChooser *fc);extern void assign_playlist_fc_filters(GtkFileChooser *fc);extern char pl_color_active[14];extern char pl_color_inactive[14];extern GtkTooltips * aqualung_tooltips;extern GtkWidget* gui_stock_label_button(gchar *blabel, const gchar *bstock);extern PangoFontDescription *fd_playlist;extern PangoFontDescription *fd_statusbar;GtkWidget * playlist_window;GtkWidget * da_dialog;GtkWidget * scrolled_win;extern GtkWidget * main_window;extern GtkWidget * info_window;extern GtkWidget * vol_window;int playlist_pos_x;int playlist_pos_y;int playlist_size_x;int playlist_size_y;int playlist_on;int playlist_color_is_set;int playlist_drag_y;int playlist_scroll_up_tag = -1;int playlist_scroll_dn_tag = -1;extern int main_size_x;extern int main_size_y;extern int main_pos_x;extern int main_pos_y;extern int browser_pos_x;extern int browser_pos_y;extern int browser_on;extern gulong play_id;extern gulong pause_id;extern GtkWidget * play_button;extern GtkWidget * pause_button;extern int vol_finished;extern int vol_index;int vol_n_tracks;int vol_is_average;vol_queue_t * pl_vol_queue;/* used to store array of tree iters of tracks selected for RVA calc */GtkTreeIter * vol_iters;GtkWidget * play_list;GtkTreeStore * play_store = 0;GtkTreeSelection * play_select;GtkTreeViewColumn * track_column;GtkTreeViewColumn * rva_column;GtkTreeViewColumn * length_column;GtkCellRenderer * track_renderer;GtkCellRenderer * rva_renderer;GtkCellRenderer * length_renderer;GtkWidget * statusbar_total;GtkWidget * statusbar_total_label;GtkWidget * statusbar_selected;GtkWidget * statusbar_selected_label;/* popup menus */GtkWidget * add_menu;GtkWidget * add__files;GtkWidget * add__dir;GtkWidget * sel_menu;GtkWidget * sel__none;GtkWidget * sel__all;GtkWidget * sel__inv;GtkWidget * rem_menu;GtkWidget * cut__sel;GtkWidget * rem__all;GtkWidget * rem__dead;GtkWidget * rem__sel;GtkWidget * plist_menu;GtkWidget * plist__save;GtkWidget * plist__load;GtkWidget * plist__enqueue;GtkWidget * plist__separator1;GtkWidget * plist__rva;GtkWidget * plist__rva_menu;GtkWidget * plist__rva_separate;GtkWidget * plist__rva_average;GtkWidget * plist__reread_file_meta;GtkWidget * plist__separator2;GtkWidget * plist__fileinfo;GtkWidget * plist__search;#ifdef HAVE_IFPGtkWidget * plist__send_songs_to_iriver;GtkWidget * plist__separator3;#endif /* HAVE_IFP */void add_directory(GtkWidget * widget, gpointer data);void init_plist_menu(GtkWidget *append_menu);void show_active_position_in_playlist(void);void show_active_position_in_playlist_toggle(void);void show_last_position_in_playlist(void);void expand_collapse_album_node(void);char command[RB_CONTROL_SIZE];char fileinfo_name[MAXLEN];char fileinfo_file[MAXLEN];extern int is_file_loaded;extern int is_paused;extern int allow_seeks;extern char current_file[MAXLEN];extern rb_t * rb_gui2disk;extern GtkWidget * playlist_toggle;typedef struct _playlist_filemeta {        char * title;        float duration;        float voladj;} playlist_filemeta;playlist_filemeta * playlist_filemeta_get(char * physical_name, char * alt_name, int composit);void playlist_filemeta_free(playlist_filemeta * plfm);void rem__sel_cb(gpointer data);void cut__sel_cb(gpointer data);void plist__search_cb(gpointer data);void add_files(GtkWidget * widget, gpointer data);void recalc_album_node(GtkTreeIter * iter);voidvoladj2str(float voladj, char * str) {	if (fabs(voladj) < 0.05f) {		sprintf(str, " %.1f dB", 0.0f);	} else {		if (voladj >= 0.0f) {			sprintf(str, " %.1f dB", voladj);		} else {			sprintf(str, "%.1f dB", voladj);		}	}}voiddisable_bold_font_in_playlist() {        GtkTreeIter iter;	int i = 0;	while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter, NULL, i++)) {		int j = 0;		GtkTreeIter iter_child;		gtk_tree_store_set(play_store, &iter, 7, PANGO_WEIGHT_NORMAL, -1);		while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter_child, &iter, j++)) {			gtk_tree_store_set(play_store, &iter_child, 7, PANGO_WEIGHT_NORMAL, -1);		}	}}voidadjust_playlist_item_color(GtkTreeIter * piter, char * active, char * inactive) {	char * str;	gtk_tree_model_get(GTK_TREE_MODEL(play_store), piter, 2, &str, -1);		if (strcmp(str, pl_color_active) == 0) {		gtk_tree_store_set(play_store, piter, 2, active, -1);		if (options.show_active_track_name_in_bold) {			gtk_tree_store_set(play_store, piter, 7, PANGO_WEIGHT_BOLD, -1);		}	}		if (strcmp(str, pl_color_inactive) == 0) {		gtk_tree_store_set(play_store, piter, 2, inactive, -1);		gtk_tree_store_set(play_store, piter, 7, PANGO_WEIGHT_NORMAL, -1);	}	g_free(str);}voidset_playlist_color() {		GtkTreeIter iter;	char active[14];	char inactive[14];	int i = 0;        sprintf(active, "#%04X%04X%04X",		play_list->style->fg[SELECTED].red,		play_list->style->fg[SELECTED].green,		play_list->style->fg[SELECTED].blue);	sprintf(inactive, "#%04X%04X%04X",		play_list->style->fg[INSENSITIVE].red,		play_list->style->fg[INSENSITIVE].green,		play_list->style->fg[INSENSITIVE].blue);	while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter, NULL, i++)) {		int j = 0;		GtkTreeIter iter_child;		adjust_playlist_item_color(&iter, active, inactive);		while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter_child, &iter, j++)) {			adjust_playlist_item_color(&iter_child, active, inactive);		}        }        strcpy(pl_color_active, active);	strcpy(pl_color_inactive, inactive);        }/* Calls foreach on each selected track iter. A track is selected iff   it is selected or its parent album node is selected. */voidplaylist_foreach_selected(void (* foreach)(GtkTreeIter *, void *), void * data) {	GtkTreeIter iter_top;	GtkTreeIter iter;	int i;	int j;	i = 0;	while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter_top, NULL, i++)) {		gboolean topsel = gtk_tree_selection_iter_is_selected(play_select, &iter_top);		if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(play_store), &iter_top)) {			j = 0;			while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(play_store), &iter, &iter_top, j++)) {				if (topsel || gtk_tree_selection_iter_is_selected(play_select, &iter)) {					(*foreach)(&iter, data);				}			}		} else if (topsel) {			(*foreach)(&iter_top, data);		}	}}GtkTreePath *get_playing_path(GtkTreeStore * store) {	GtkTreeIter iter;	GtkTreeIter iter_child;	char * str;	int i = 0;	if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter))		return NULL;	do {		int j = 0;		gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, 2, &str, -1);		while (gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(store), &iter_child, &iter, j++)) {			gtk_tree_model_get(GTK_TREE_MODEL(store), &iter_child, 2, &str, -1);			if (strcmp(str, pl_color_active) == 0) {				g_free(str);				return gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter_child);			}			g_free(str);		}		if (j == 1) { /* toplevel leafnode a.k.a. ordinary track */			if (strcmp(str, pl_color_active) == 0) {				g_free(str);				return gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);			}					g_free(str);		}			} while (i++, gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter));	return NULL;}void start_playback_from_playlist(GtkTreePath * path) {	GtkTreeIter iter;	GtkTreePath * p;	char cmd;	cue_t cue;        	if (!allow_seeks)		return;	p = get_playing_path(play_store);	if (p != NULL) {		gtk_tree_model_get_iter(GTK_TREE_MODEL(play_store), &iter, p);		gtk_tree_path_free(p);                unmark_track(&iter);	}		gtk_tree_model_get_iter(GTK_TREE_MODEL(play_store), &iter, path);	if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(play_store), &iter) > 0) {		GtkTreeIter iter_child;		gtk_tree_model_iter_children(GTK_TREE_MODEL(play_store), &iter_child, &iter);		mark_track(&iter_child);	} else {		mark_track(&iter);	}		p = get_playing_path(play_store);	gtk_tree_model_get_iter(GTK_TREE_MODEL(play_store), &iter, p);	gtk_tree_path_free(p);	cue_track_for_playback(&iter, &cue);        if (options.show_sn_title) {		refresh_displays();        }	toggle_noeffect(PLAY, TRUE);	if (is_paused) {		is_paused = 0;		toggle_noeffect(PAUSE, FALSE);	}			cmd = CMD_CUE;	rb_write(rb_gui2disk, &cmd, sizeof(char));	rb_write(rb_gui2disk, (void *)&cue, sizeof(cue_t));	try_waking_disk_thread();		is_file_loaded = 1;}static gbooleanplaylist_window_close(GtkWidget * widget, GdkEvent * event, gpointer data) {	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(playlist_toggle), FALSE);	return TRUE;}gintplaylist_window_key_pressed(GtkWidget * widget, GdkEventKey * kevent) {	GtkTreePath * path;	GtkTreeViewColumn * column;	GtkTreeIter iter;	char * pname;	char * pfile;        switch (kevent->keyval) {        case GDK_Insert:	case GDK_KP_Insert:                if(kevent->state & GDK_SHIFT_MASK) {  /* SHIFT + Insert */                        add_directory(NULL, NULL);                } else {                        add_files(NULL, NULL);                }                return TRUE;                break;        case GDK_q:	case GDK_Q:	case GDK_Escape:                if (!options.playlist_is_embedded) {                        playlist_window_close(NULL, NULL, NULL);		}		return TRUE;		break;	case GDK_F1:	case GDK_i:	case GDK_I:		gtk_tree_view_get_cursor(GTK_TREE_VIEW(play_list), &path, &column);		if (path &&		    gtk_tree_model_get_iter(GTK_TREE_MODEL(play_store), &iter, path) &&		    !gtk_tree_model_iter_has_child(GTK_TREE_MODEL(play_store), &iter)) {			GtkTreeIter dummy;						gtk_tree_model_get(GTK_TREE_MODEL(play_store), &iter,					   0, &pname, 1, &pfile, -1);						strncpy(fileinfo_name, pname, MAXLEN-1);			strncpy(fileinfo_file, pfile, MAXLEN-1);			free(pname);			free(pfile);			show_file_info(fileinfo_name, fileinfo_file, 0, NULL, dummy);		}		return TRUE;		break;	case GDK_Return:	case GDK_KP_Enter:		gtk_tree_view_get_cursor(GTK_TREE_VIEW(play_list), &path, &column);		if (path) {			start_playback_from_playlist(path);		}				return TRUE;		break;	case GDK_u:	case GDK_U:		cut__sel_cb(NULL);		return TRUE;		break;	case GDK_f:	case GDK_F:		plist__search_cb(NULL);		return TRUE;		break;        case GDK_a:        case GDK_A:

⌨️ 快捷键说明

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