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

📄 playlist.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  XMMS - Cross-platform multimedia player *  Copyright (C) 1998-2003  Peter Alm, Mikael Alm, Olle Hallnas, *                           Thomas Nilsson and 4Front Technologies *  Copyright (C) 1999-2004  Haavard Kvaalen * *  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. */#include "xmms.h"#include <time.h>#include "libxmms/util.h"#include <sys/stat.h>#include <unistd.h>GList *playlist = NULL;GList *shuffle_list = NULL;GList *queued_list = NULL;static gboolean playlist_get_info_scan_active = FALSE;gboolean playlist_get_info_going = FALSE;static pthread_t playlist_get_info_thread;pthread_mutex_t playlist_mutex = PTHREAD_MUTEX_INITIALIZER;static PlaylistEntry *playlist_position;extern PlayList_List *playlistwin_list;extern Vis *mainwin_vis;extern SVis *mainwin_svis;static gboolean playlist_get_info_entry(PlaylistEntry *entry);static int playlist_sort_str_by_path_cmpfunc(gconstpointer a, gconstpointer b);static guint playlist_load_ins(char * filename, long pos);static void playlist_load_ins_file(char *filename, char *playlist_name, long pos, char *title, int len);static int __get_playlist_length(void);static void playlist_generate_shuffle_list(void);static void __playlist_generate_shuffle_list(void);struct devino {	dev_t dev;	ino_t ino;};static GList *find_playlist_position_list(void){	/* Caller should hold playlist-mutex */	if (!playlist_position)	{		if (cfg.shuffle)			return shuffle_list;		return playlist;	}	if (cfg.shuffle)		return g_list_find(shuffle_list, playlist_position);	return g_list_find(playlist, playlist_position);}static void play_queued(void){	/* Caller should hold playlist-mutex */	GList *temp = queued_list;		playlist_position = queued_list->data;	queued_list = g_list_remove_link(queued_list, queued_list);	g_list_free_1(temp);}void playlist_clear(void){	GList *node;	PlaylistEntry *entry;		if (get_input_playing())		input_stop();	pthread_mutex_lock(&playlist_mutex);	if (playlist)	{		node = playlist;		while (node)		{			entry = node->data;			if (entry->filename)				g_free(entry->filename);			if (entry->title)				g_free(entry->title);			g_free(entry);			node = node->next;		}		g_list_free(playlist);		playlist = NULL;		playlist_position = NULL;	}	pthread_mutex_unlock(&playlist_mutex);	playlist_generate_shuffle_list();	playlistwin_update_list();}void playlist_delete_node(GList *node, gboolean *set_info_text, gboolean *restart_playing){	/* Caller should hold playlist mutex */	PlaylistEntry *entry;	GList *playing_song = NULL;	GList *queued_song = NULL;	/*	 * We call g_list_find manually here because	 * we don't want an item in the shuffle_list	 */	if (playlist_position)		playing_song = g_list_find(playlist, playlist_position);	entry = node->data;	if (playing_song == node)	{		*set_info_text = TRUE;		if (get_input_playing())		{			PL_UNLOCK();			input_stop();			PL_LOCK();			*restart_playing = TRUE;		}		playing_song = find_playlist_position_list();		if (g_list_next(playing_song))			playlist_position = playing_song->next->data;		else if (g_list_previous(playing_song))			playlist_position = playing_song->prev->data;		else			playlist_position = NULL;		/* Make sure the entry did not disappear under us */		if (g_list_index(get_playlist(), entry) == -1)			return;	}	else if (playing_song &&		 g_list_position(playlist, playing_song) >		 g_list_position(playlist, node))		*set_info_text = TRUE;	if ((queued_song = g_list_find(queued_list, entry)) != NULL)	{		queued_list = g_list_remove_link(queued_list, queued_song);		g_list_free_1(queued_song);	}	if (entry->filename)		g_free(entry->filename);	if (entry->title)		g_free(entry->title);	shuffle_list = g_list_remove(shuffle_list, entry);	playlist = g_list_remove_link(playlist, node);	g_free(entry);	g_list_free_1(node);}void playlist_delete_index(glong index){	gboolean restart_playing = FALSE, set_info_text = FALSE;	GList *node;		PL_LOCK();	if (!playlist)	{		PL_UNLOCK();		return;	}	node = g_list_nth(playlist, index);	if(!node)	{		PL_UNLOCK();		return;	}	playlist_delete_node(node, &set_info_text, &restart_playing);	PL_UNLOCK();	playlistwin_update_list();	if (restart_playing)	{		if (playlist_position)			playlist_play();		else			mainwin_clear_song_info();	}	else if (set_info_text)		mainwin_set_info_text();}void playlist_delete_filenames(GList *filenames){	GList *node, *fnode;	gboolean set_info_text = FALSE, restart_playing = FALSE;	PL_LOCK();	for (fnode = filenames; fnode; fnode = g_list_next(fnode))	{		node = playlist;		while (node)		{			GList *next = g_list_next(node);			PlaylistEntry *entry = node->data;			if (!strcmp(entry->filename, fnode->data))				playlist_delete_node(node, &set_info_text,						     &restart_playing);			node = next;		}	}	PL_UNLOCK();	playlistwin_update_list();	if (restart_playing)	{		if (playlist_position)			playlist_play();		else			mainwin_clear_song_info();	}	else if (set_info_text)		mainwin_set_info_text();	}void playlist_delete(gboolean crop){	gboolean restart_playing = FALSE, set_info_text = FALSE;	GList *node, *next;	PlaylistEntry *entry;	pthread_mutex_lock(&playlist_mutex);	node = playlist;	while (node)	{		entry = node->data;		next = g_list_next(node);		if ((entry->selected && !crop) || (!entry->selected && crop))			playlist_delete_node(node, &set_info_text, &restart_playing);		node = next;	}	pthread_mutex_unlock(&playlist_mutex);		playlistwin_update_list();	if (set_info_text)		mainwin_set_info_text();	if (restart_playing)	{		if (playlist_position)			playlist_play();		else			mainwin_clear_song_info();	}}static void __playlist_ins_with_info(char *filename, long pos, char* title, int len){	PlaylistEntry *entry;	entry = g_malloc0(sizeof (PlaylistEntry));	entry->filename = g_strdup(filename);	if (title)		entry->title = g_strdup(title);	entry->length = len;	pthread_mutex_lock(&playlist_mutex);	playlist = g_list_insert(playlist, entry, pos);	pthread_mutex_unlock(&playlist_mutex);			playlist_get_info_scan_active = TRUE;}static void __playlist_ins(char * filename, long pos){	__playlist_ins_with_info(filename, pos, NULL, -1);}static gboolean is_playlist_name(char *pathname){	char *ext;	ext = strrchr (pathname, '.');	if (ext && ((!strcasecmp(ext, ".m3u") || !strcasecmp(ext, ".pls"))))		return TRUE;	return FALSE;}void playlist_ins(char * filename, long pos){	gboolean ispl = FALSE;	ispl = is_playlist_name (filename);	if (!ispl && !input_check_file(filename))	{		/*		 * Some files (typically produced by some cgi-scripts)		 * don't have the correct extension.  Try to recognize		 * these files by looking at their content.  We only		 * check for http entries since it does not make sense		 * to have file entries in a playlist fetched from the		 * net.		 */		struct stat stat_buf;	    		/*		 * Some strange people put fifo's with the .mp3 extension,		 * so we need to make sure it's a real file.  This is not		 * supposed to be for security, else we'd open then do		 * fstat()		 */		if (!stat(filename, &stat_buf) && S_ISREG(stat_buf.st_mode))		{			char buf[64], *p;			FILE *file;			int r;			if ((file = fopen(filename, "r")) != NULL)			{				r = fread(buf, 1, sizeof(buf), file);				fclose(file);				for (p = buf; r-- > 0 && (*p == '\r' || *p == '\n'); p++)					;				if (r > 5 && !strncasecmp(p, "http:", 5))					ispl = TRUE;			}		}	}	if (ispl)		playlist_load_ins(filename, pos);	else		if (input_check_file(filename))		{			__playlist_ins(filename, pos);			playlist_generate_shuffle_list();			playlistwin_update_list();		}}static guint devino_hash(gconstpointer key){	const struct devino *d = key;	return d->ino;}static int devino_compare(gconstpointer a, gconstpointer b){	const struct devino *da = a, *db = b;	return da->dev == db->dev && da->ino == db->ino;}static gboolean devino_destroy(gpointer key, gpointer value, gpointer data){	g_free(key);	return TRUE;}static GList* playlist_dir_find_files(char *path, gboolean background, GHashTable *htab){	DIR *dir;	struct dirent *dirent;	struct stat statbuf;	char *temp;	GList *list = NULL, *ilist;	struct devino *devino;	if (stat(path, &statbuf) < 0)		return NULL;	if (!S_ISDIR(statbuf.st_mode))		return NULL;	devino = g_malloc(sizeof (*devino));	devino->dev = statbuf.st_dev;	devino->ino = statbuf.st_ino;	if (g_hash_table_lookup(htab, devino))	{		g_free(devino);		return NULL;	}	g_hash_table_insert(htab, devino, GINT_TO_POINTER(1));	if (path[strlen(path) - 1] != '/')		temp = g_strconcat(path, "/", NULL);	else		temp = g_strdup(path);	if ((ilist = input_scan_dir(temp)) != NULL)	{		GList *node;		node = ilist;		while (node)		{			char *name = g_strconcat(temp, node->data, NULL);			list = g_list_prepend(list, name);			g_free(node->data);			node = g_list_next(node);		}		g_list_free(ilist);		g_free(temp);		return list;	}	if ((dir = opendir(path)) == NULL)	{		g_free(temp);		return 0;	}	while ((dirent = readdir(dir)) != NULL)	{		char *filename;		if (dirent->d_name[0] == '.')			continue;		filename = g_strconcat(temp, dirent->d_name, NULL);		if (stat(filename, &statbuf) < 0)		{			g_free(filename);			continue;		}		if (S_ISDIR(statbuf.st_mode))		{			GList *sub;			sub = playlist_dir_find_files(filename,						      background, htab);			g_free(filename);			list = g_list_concat(list, sub);		}		else if (input_check_file(filename))			list = g_list_prepend(list, filename);		else			g_free(filename);		while (background && gtk_events_pending())			gtk_main_iteration();	}	closedir(dir);	g_free(temp);	return list;}guint playlist_ins_dir(char *path, long pos, gboolean background){	guint entries = 0;	GList *list, *node;	GHashTable *htab;	htab = g_hash_table_new(devino_hash, devino_compare);	list = playlist_dir_find_files(path, background, htab);	list = g_list_sort(list, playlist_sort_str_by_path_cmpfunc);	g_hash_table_foreach_remove(htab, devino_destroy, NULL);		node = list;	while (node)	{		__playlist_ins(node->data, pos);		entries++;		if (pos >= 0)			pos++;		g_free(node->data);		node = g_list_next(node);	}	g_list_free(list);	playlist_generate_shuffle_list();	playlistwin_update_list();	return entries;}guint playlist_ins_url_string(char * string, long pos){	char *temp;	struct stat statbuf;	int i = 1, entries = 0;	while (*string)	{		temp = strchr(string, '\n');		if (temp)		{			if (*(temp - 1) == '\r')				*(temp - 1) = '\0';			*temp = '\0';		}		if (!strncasecmp(string, "file:", 5)) {			if(!xmms_urldecode_path(string))				return 0;		}		stat(string, &statbuf);		if (S_ISDIR(statbuf.st_mode))			i = playlist_ins_dir(string, pos, FALSE);		else		{			if (is_playlist_name (string))				i = playlist_load_ins(string, pos);			else			{				playlist_ins(string, pos);				i = 1;			}		}		entries += i;		if (pos >= 0)			pos += i;		if (!temp)			break;		string = temp + 1;	}	playlist_generate_shuffle_list();	playlistwin_update_list();	return entries;}void playlist_play(void){	char *filename = NULL;	if (get_playlist_length() == 0)		return;	/* If the user wants a skin randomly selected on play */	if (cfg.random_skin_on_play)	{		/* Get the current skin list */		scan_skins();		/* If there are entries */		if (g_list_length(skinlist)) {			/* Get a random value to select the skin to use */			int randval = random() % (g_list_length(skinlist) + 1);			/* If the random value is 0, use the default skin */			/* Otherwise subtract 1 from the random value and */			/* select the skin */			if (randval == 0)				load_skin(NULL);			else			{				struct SkinNode *skin;				skin = g_list_nth(skinlist, randval - 1)->data;				load_skin(skin->path);			}		}		/* Call scan_skins() again to make sure skin selector */		/* is up to date */		scan_skins();	}	if (get_input_playing())		input_stop();	vis_clear_data(mainwin_vis);	vis_clear_data(playlistwin_vis);	svis_clear_data(mainwin_svis);	mainwin_disable_seekbar();	PL_LOCK();	if (playlist)	{		if (!playlist_position)		{			if (cfg.shuffle)				playlist_position = shuffle_list->data;			else				playlist_position = playlist->data;		}		filename = playlist_position->filename;	}	PL_UNLOCK();	if (!filename)		return;		input_play(filename);	if (input_get_time() != -1)	{		equalizerwin_load_auto_preset(filename);		input_set_eq(cfg.equalizer_active, cfg.equalizer_preamp,			     cfg.equalizer_bands);	}	playlist_check_pos_current();}void playlist_set_info(char *title, int length, int rate, int freq, int nch){	PL_LOCK();	if (playlist_position)	{		g_free(playlist_position->title);		playlist_position->title = g_strdup(title);		playlist_position->length = length;	}	PL_UNLOCK();	mainwin_set_song_info(rate, freq, nch);}void playlist_check_pos_current(void){	int pos, row, bottom;	PL_LOCK();	if (!playlist || !playlist_position || !playlistwin_list)	{		PL_UNLOCK();		return;	}	pos = g_list_index(playlist, playlist_position);	if (playlistwin_item_visible(pos))	{		PL_UNLOCK();		return;	}	bottom = MAX(0, __get_playlist_length() -		     playlistwin_list->pl_num_visible);	row = CLAMP(pos - playlistwin_list->pl_num_visible / 2, 0, bottom);	PL_UNLOCK();	playlistwin_set_toprow(row);}void playlist_next(void){	GList *plist_pos_list;	gboolean restart_playing = FALSE;	PL_LOCK();	if (!playlist)	{		PL_UNLOCK();		return;	}	plist_pos_list = find_playlist_position_list();	if (!cfg.repeat && !g_list_next(plist_pos_list))	{		PL_UNLOCK();		return;	}		if (get_input_playing())	{		/* We need to stop before changing playlist_position */		PL_UNLOCK();		input_stop();		PL_LOCK();		restart_playing = TRUE;	}	plist_pos_list = find_playlist_position_list();	if (queued_list)		play_queued();	else if (g_list_next(plist_pos_list))		playlist_position = plist_pos_list->next->data;	else if (cfg.repeat)	{		playlist_position = NULL;		__playlist_generate_shuffle_list();		if (cfg.shuffle)			playlist_position = shuffle_list->data;		else			playlist_position = playlist->data;	}	PL_UNLOCK();	playlist_check_pos_current();	if (restart_playing)		playlist_play();	else	{		mainwin_set_info_text();		playlistwin_update_list();	}}void playlist_prev(void){	GList *plist_pos_list;

⌨️ 快捷键说明

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