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

📄 local.c

📁 linux下网络收音机的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Copyright (c) 2002, 2003, 2004 Jean-Yves Lefort <jylefort@brutele.be> * * 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 "config.h"#include <stdio.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <glib/gi18n.h>#ifdef WITH_LOCAL_METADATA#include <tag_c.h>#endif#include "streamtuner.h"/*** cpp *********************************************************************/#define POINTER_TO_STRING(ptr)	((ptr) ? (ptr) : "")/*** type definitions ********************************************************/typedef struct{  STStream	stream;  char		*pathname;	/* full pathname, in the fs locale */  char		*filename;	/* filename only, converted to UTF-8 */  char		*title;  char		*artist;  char		*album;  char		*year;  char		*genre;  char		*comment;  char		*duration;  int		bitrate;  int		samplerate;  int		channels;} LocalStream;enum {  FIELD_PATHNAME,  FIELD_FILENAME,  FIELD_TITLE,  FIELD_ARTIST,  FIELD_ALBUM,  FIELD_YEAR,  FIELD_GENRE,  FIELD_COMMENT,  FIELD_DURATION,  FIELD_BITRATE,  FIELD_SAMPLERATE,  FIELD_CHANNELS,  FIELD_AUDIO		/* meta field (bitrate, samplerate and channels) */};/*** variables ***************************************************************/static STPlugin *local_plugin = NULL;static STHandler *local_handler = NULL;/*** function declarations ***************************************************/static LocalStream *stream_new_cb (gpointer data);static void stream_field_get_cb (LocalStream *stream,				 STHandlerField *field,				 GValue *value,				 gpointer data);static void stream_field_set_cb (LocalStream *stream,				 STHandlerField *field,				 const GValue *value,				 gpointer data);static void stream_stock_field_get_cb (LocalStream *stream,				       STHandlerStockField stock_field,				       GValue *value,				       gpointer data);static gboolean stream_modify_cb (LocalStream *stream,				  GSList *fields,				  GSList *values,				  gpointer data,				  GError **err);static gboolean stream_delete_cb (LocalStream *stream,				  gpointer data,				  GError **err);static void stream_free_cb (LocalStream *stream, gpointer data);static gboolean stream_rename (LocalStream *stream,			       const GValue *new_filename,			       GError **err);static gboolean stream_tune_in_multiple_cb (GSList *streams,					    gpointer data,					    GError **err);static gboolean stream_browse_cb (LocalStream *stream,				  gpointer data,				  GError **err);static gboolean reload_cb (STCategory *category,			   GNode **categories,			   GList **streams,			   gpointer data,			   GError **err);static gboolean reload_categories (const char *music_dir,				   GNode *root,				   GError **err);static gboolean reload_streams (const char *music_dir,				STCategory *category,				GList **streams,				GError **err);#ifdef WITH_LOCAL_METADATAstatic void metadata_read (LocalStream *stream);static gboolean metadata_write (LocalStream *stream,				GSList *fields,				GSList *values,				GError **err);#endif /* WITH_LOCAL_METADATA */static void init_handler (void);static gboolean check_api_version (GError **err);/*** implementation **********************************************************/static LocalStream *stream_new_cb (gpointer data){  return g_new0(LocalStream, 1);}static voidstream_field_get_cb (LocalStream *stream,		     STHandlerField *field,		     GValue *value,		     gpointer data){  switch (field->id)    {    case FIELD_PATHNAME:      g_value_set_string(value, stream->pathname);      break;    case FIELD_FILENAME:      g_value_set_string(value, stream->filename);      break;    case FIELD_TITLE:      g_value_set_string(value, stream->title);      break;    case FIELD_ARTIST:      g_value_set_string(value, stream->artist);      break;    case FIELD_ALBUM:      g_value_set_string(value, stream->album);      break;          case FIELD_YEAR:      g_value_set_string(value, stream->year);      break;    case FIELD_GENRE:      g_value_set_string(value, stream->genre);      break;    case FIELD_COMMENT:      g_value_set_string(value, stream->comment);      break;    case FIELD_DURATION:      g_value_set_string(value, stream->duration);      break;    case FIELD_BITRATE:      g_value_set_int(value, stream->bitrate);      break;    case FIELD_SAMPLERATE:      g_value_set_int(value, stream->samplerate);      break;    case FIELD_CHANNELS:      g_value_set_int(value, stream->channels);      break;    case FIELD_AUDIO:      g_value_take_string(value, st_format_audio_properties(stream->bitrate,							    stream->samplerate,							    stream->channels));      break;    default:      g_assert_not_reached();    }}static voidstream_field_set_cb (LocalStream *stream,		     STHandlerField *field,		     const GValue *value,		     gpointer data){  switch (field->id)    {    case FIELD_PATHNAME:      stream->pathname = g_value_dup_string(value);      break;    case FIELD_FILENAME:      stream->filename = g_value_dup_string(value);      break;    case FIELD_TITLE:      stream->title = g_value_dup_string(value);      break;    case FIELD_ARTIST:      stream->artist = g_value_dup_string(value);      break;    case FIELD_ALBUM:      stream->album = g_value_dup_string(value);      break;          case FIELD_YEAR:      stream->year = g_value_dup_string(value);      break;    case FIELD_GENRE:      stream->genre = g_value_dup_string(value);      break;    case FIELD_COMMENT:      stream->comment = g_value_dup_string(value);      break;    case FIELD_DURATION:      stream->duration = g_value_dup_string(value);      break;    case FIELD_BITRATE:      stream->bitrate = g_value_get_int(value);      break;    case FIELD_SAMPLERATE:      stream->samplerate = g_value_get_int(value);      break;    case FIELD_CHANNELS:      stream->channels = g_value_get_int(value);      break;    default:      g_assert_not_reached();    }}static voidstream_stock_field_get_cb (LocalStream *stream,			   STHandlerStockField stock_field,			   GValue *value,			   gpointer data){  switch (stock_field)    {    case ST_HANDLER_STOCK_FIELD_NAME:      {	char *name;	if (stream->artist && stream->title)	  name = g_strdup_printf("%s - %s", stream->artist, stream->title);	else if (stream->title)	  name = g_strdup(stream->title);	else	  name = g_strdup(stream->filename);	g_value_set_string(value, name);	g_free(name);	break;      }    case ST_HANDLER_STOCK_FIELD_GENRE:      g_value_set_string(value, stream->genre);      break;    case ST_HANDLER_STOCK_FIELD_DESCRIPTION:      g_value_set_string(value, stream->comment);      break;    case ST_HANDLER_STOCK_FIELD_HOMEPAGE:      /* nop */      break;    case ST_HANDLER_STOCK_FIELD_URI_LIST:      {	char *uri;	GError *err = NULL;	uri = g_filename_to_uri(stream->pathname, NULL, &err);	if (uri)	  {	    GValueArray *value_array;	    GValue uri_value = { 0, };	    	    value_array = g_value_array_new(1);	    g_value_init(&uri_value, G_TYPE_STRING);	    g_value_take_string(&uri_value, uri);	    g_value_array_append(value_array, &uri_value);	    g_value_unset(&uri_value);	    g_value_take_boxed(value, value_array);	  }	else	  {	    st_handler_notice(local_handler, _("%s: unable to convert filename to URI: %s"), stream->pathname, err->message);	    g_error_free(err);	  }	break;      }    }}static gbooleanstream_modify_cb (LocalStream *stream,		  GSList *fields,		  GSList *values,		  gpointer data,		  GError **err){  GSList *f;  GSList *v;  gboolean modify_file = FALSE;  for (f = fields, v = values; f && v; f = f->next, v = v->next)    {      STHandlerField *field = f->data;      const GValue *value = v->data;      switch (field->id)	{	case FIELD_FILENAME:	  if (! stream_rename(stream, value, err))	    return FALSE;	  break;	case FIELD_TITLE:	case FIELD_ARTIST:	case FIELD_ALBUM:	case FIELD_YEAR:	case FIELD_GENRE:	case FIELD_COMMENT:	  modify_file = TRUE;	  break;	default:	  g_assert_not_reached();	}    }  if (modify_file)    {#ifdef WITH_LOCAL_METADATA      if (! metadata_write(stream, fields, values, err))	return FALSE;#else      g_set_error(err, 0, 0, _("metadata support is disabled"));      return FALSE;#endif /* WITH_LOCAL_METADATA */    }  return TRUE;}static gbooleanstream_delete_cb (LocalStream *stream, gpointer data, GError **err){  if (unlink(stream->pathname) < 0)    {      g_set_error(err, 0, 0, "%s", g_strerror(errno));      return FALSE;    }  else    return TRUE;}static voidstream_free_cb (LocalStream *stream, gpointer data){  g_free(stream->pathname);  g_free(stream->filename);  g_free(stream->title);  g_free(stream->artist);  g_free(stream->album);  g_free(stream->year);  g_free(stream->genre);  g_free(stream->comment);  g_free(stream->duration);  st_stream_free((STStream *) stream);}static gbooleanstream_rename (LocalStream *stream, const GValue *new_filename, GError **err){  GError *tmp_err = NULL;  char *filename;  char *directory;  char *new_pathname;  g_return_val_if_fail(stream != NULL, FALSE);  g_return_val_if_fail(G_IS_VALUE(new_filename), FALSE);  filename = g_filename_from_utf8(g_value_get_string(new_filename), -1, NULL, NULL, &tmp_err);  if (! filename)    {      g_set_error(err, 0, 0, _("unable to convert filename from UTF-8 encoding: %s"), tmp_err->message);      g_error_free(tmp_err);      return FALSE;    }  directory = g_path_get_dirname(stream->pathname);  new_pathname = g_build_filename(directory, filename, NULL);  g_free(directory);  if (g_file_test(new_pathname, G_FILE_TEST_EXISTS))    {      g_set_error(err, 0, 0, _("target file already exists"));      g_free(filename);      g_free(new_pathname);            return FALSE;    }  if (rename(stream->pathname, new_pathname) < 0)    {      g_set_error(err, 0, 0, "%s", g_strerror(errno));      g_free(filename);      g_free(new_pathname);      return FALSE;    }  /* success */  stream->pathname = new_pathname;  stream->filename = g_value_dup_string(new_filename);  return TRUE;}static gbooleanstream_tune_in_multiple_cb (GSList *streams, gpointer data, GError **err){  char *m3uname;  GSList *filenames = NULL;  GSList *l;  gboolean status;  /* create a list of filenames from STREAMS */  for (l = streams; l; l = l->next)    {      LocalStream *stream = l->data;      filenames = g_slist_append(filenames, stream->pathname);    }  /* write the .m3u */  m3uname = st_m3u_mktemp("streamtuner.local.XXXXXX", filenames, err);  g_slist_free(filenames);  if (! m3uname)    return FALSE;  /* open the .m3u */  status = st_action_run("play-m3u", m3uname, err);  g_free(m3uname);  return status;}static gbooleanstream_browse_cb (LocalStream *stream, gpointer data, GError **err){  char *url;  char *s;  gboolean status;  if (stream->album)    url = g_strconcat("http://www.allmusic.com/cg/amg.dll?p=amg&opt1=2&sql=", stream->album, NULL);  else if (stream->title)    url = g_strconcat("http://www.allmusic.com/cg/amg.dll?p=amg&opt1=3&sql=", stream->title, NULL);  else if (stream->artist)    url = g_strconcat("http://www.allmusic.com/cg/amg.dll?p=amg&opt1=1&sql=", stream->artist, NULL);  else    {      g_set_error(err, 0, 0, _("file has no album, title or artist information"));      return FALSE;    }  /* allmusic.com needs this */  for (s = url; *s; s++)    if (*s == ' ')      *s = '|';  status = st_action_run("view-web", url, err);  g_free(url);    return status;}static gbooleanreload_cb (STCategory *category,

⌨️ 快捷键说明

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