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

📄 live365.c

📁 linux下网络收音机的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2002, 2003, 2004 Jean-Yves Lefort * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */#include "config.h"#include <string.h>#include <stdlib.h>#include <glib/gi18n.h>#include "streamtuner.h"/*** cpp *********************************************************************/#define LIVE365_ROOT		"http://www.live365.com/"#define DIRECTORY_PREFIX	"cgi-bin/directory.cgi?genre="#define MAX_STREAMS_PER_PAGE	200 /* enforced by Live365 */#define PARSE_ERROR		st_handler_notice(live365_handler, _("parse error at %s"), G_STRLOC)#define CONFIG_USE_MEMBERSHIP		"use-membership"#define CONFIG_NAME			"name"#define CONFIG_PASSWORD			"password"#define CONFIG_STREAM_LIMIT_ENABLED	"stream-limit-enabled"#define CONFIG_STREAM_LIMIT		"stream-limit"#define MIN_STREAM_LIMIT	0#define MAX_STREAM_LIMIT	9999/*** types *******************************************************************/typedef enum{  ACCESS_ALL,  ACCESS_VIP,  ACCESS_SUBSCRIPTION} Access;typedef struct{  STStream	stream;    char		*title;  char		*genre;  char		*description;  char		*broadcaster;  char		*audio;  char		*homepage;  int		station_id;  Access	access;  int		tlh;  double	rating;} Live365Stream;typedef struct{  char		*sane_id;  char		*session_id;} LoginInfo;typedef struct{  GNode		**categories;  GNode		*parent;} ReloadCategoriesInfo;typedef struct{  GList			**streams;  Live365Stream		*stream;  Live365Stream		*finished_stream;  gboolean		has_next_page;} ReloadStreamsInfo;enum {  FIELD_TITLE,  FIELD_GENRE,  FIELD_DESCRIPTION,  FIELD_BROADCASTER,  FIELD_AUDIO,  FIELD_HOMEPAGE,  FIELD_STATION_ID,  FIELD_URL,  FIELD_ACCESS,  FIELD_ACCESS_STRING,  FIELD_TLH,  FIELD_RATING,  FIELD_RATING_STRING};/*** variables ***************************************************************/static STPlugin *live365_plugin = NULL;static STHandler *live365_handler = NULL;static GNode *session_categories = NULL;static GtkWidget *preferences_stream_limit_check;static GtkWidget *preferences_stream_limit_spin;static GtkWidget *preferences_stream_limit_label;static GtkWidget *preferences_use_membership_check;static GtkWidget *preferences_name_label;static GtkWidget *preferences_name_entry;static GtkWidget *preferences_password_label;static GtkWidget *preferences_password_entry;/*** functions ***************************************************************/static Live365Stream	*stream_new_cb		(gpointer	data);static void		stream_field_get_cb	(Live365Stream	*stream,						 STHandlerField	*field,						 GValue		*value,						 gpointer	data);static void		stream_field_set_cb	(Live365Stream	*stream,						 STHandlerField	*field,						 const GValue	*value,						 gpointer	data);static void		stream_stock_field_get_cb (Live365Stream	*stream,						   STHandlerStockField	stock_field,						   GValue		*value,						   gpointer		data);static void		stream_free_cb		(Live365Stream	*stream,						 gpointer	data);static char		*stream_get_url		(Live365Stream	*stream,						 gboolean	blocking);static gboolean		stream_tune_in_cb	(Live365Stream	*stream,						 gpointer	data,						 GError		**err);static gboolean		stream_record_cb	(Live365Stream	*stream,						 gpointer	data,						 GError		**err);static gboolean		stream_browse_cb	(Live365Stream	*stream,						 gpointer	data,						 GError		**err);static char		*get_session_params	(gboolean	blocking);static gboolean		login			(const char	*name,						 const char	*password,						 char		**sane_id,						 char		**session_id,						 GError		**err);static void		login_header_cb		(const char	*line,						 gpointer	data);static gboolean		reload_cb		(STCategory	*category,						 GNode		**categories,						 GList		**streams,						 gpointer	data,						 GError		**err);static GNode *		categories_copy		(void);static gboolean		categories_copy_cb	(GNode		*node,						 gpointer	data);static gboolean		reload_categories	(GNode		**categories,						 GError		**err);static void		reload_categories_body_cb (const char	*line,						   gpointer	data);static gboolean		reload_streams		(STCategory	*category,						 GList		**streams,						 GError		**err);static void		reload_streams_body_cb	(const char	*line,						 gpointer	data);static gboolean		search_url_cb		(STCategory	*category);static GtkWidget *	preferences_widget_new_cb	(gpointer        data);static void		preferences_update_sensitivity	(void);static void		preferences_stream_limit_toggled_h        (GtkToggleButton *button,								   gpointer        user_data);static void		preferences_stream_limit_changed_h        (GtkSpinButton   *spin,								   gpointer        user_data);static void		preferences_use_membership_toggled_h      (GtkToggleButton *button,								   gpointer        user_data);static void		preferences_credentials_activate_h        (GtkEntry        *entry,								   gpointer        user_data);static gboolean		preferences_credentials_focus_out_event_h (GtkWidget       *widget,								   GdkEventFocus   *event,								   gpointer        user_data);static void		init_handler		(void);static gboolean		check_api_version	(GError		**err);/*** implementation **********************************************************/static Live365Stream *stream_new_cb (gpointer data){  return g_new0(Live365Stream, 1);}static voidstream_field_get_cb (Live365Stream *stream,		     STHandlerField *field,		     GValue *value,		     gpointer data){  switch (field->id)    {    case FIELD_TITLE:      g_value_set_string(value, stream->title);      break;    case FIELD_GENRE:      g_value_set_string(value, stream->genre);      break;    case FIELD_DESCRIPTION:      g_value_set_string(value, stream->description);      break;    case FIELD_BROADCASTER:      g_value_set_string(value, stream->broadcaster);      break;    case FIELD_AUDIO:       g_value_set_string(value, stream->audio);      break;    case FIELD_HOMEPAGE:      g_value_set_string(value, stream->homepage);      break;    case FIELD_STATION_ID:      g_value_set_int(value, stream->station_id);      break;    case FIELD_URL:      g_value_take_string(value, stream_get_url(stream, FALSE));      break;    case FIELD_ACCESS:      g_value_set_int(value, stream->access);      break;    case FIELD_ACCESS_STRING:      {	const char *str = NULL;	switch (stream->access)	  {	  case ACCESS_ALL:		str = _("All"); break;	  case ACCESS_VIP:		str = _("VIP"); break;	  case ACCESS_SUBSCRIPTION:	str = _("Subscription"); break;	  }	g_value_set_string(value, str);	break;      }    case FIELD_TLH:      g_value_set_int(value, stream->tlh);      break;    case FIELD_RATING:      g_value_set_double(value, stream->rating);      break;    case FIELD_RATING_STRING:      g_value_take_string(value, g_strdup_printf("%.2f", stream->rating));      break;          default:      g_assert_not_reached();    }}static voidstream_field_set_cb (Live365Stream *stream,		     STHandlerField *field,		     const GValue *value,		     gpointer data){  switch (field->id)    {    case FIELD_TITLE:      stream->title = g_value_dup_string(value);      break;    case FIELD_GENRE:      stream->genre = g_value_dup_string(value);      break;    case FIELD_DESCRIPTION:       stream->description = g_value_dup_string(value);      break;    case FIELD_BROADCASTER:      stream->broadcaster = g_value_dup_string(value);      break;    case FIELD_AUDIO:       stream->audio = g_value_dup_string(value);      break;    case FIELD_HOMEPAGE:      stream->homepage = g_value_dup_string(value);      break;    case FIELD_STATION_ID:      stream->station_id = g_value_get_int(value);      break;    case FIELD_ACCESS:      stream->access = g_value_get_int(value);      break;    case FIELD_TLH:      stream->tlh = g_value_get_int(value);      break;    case FIELD_RATING:      stream->rating = g_value_get_double(value);      break;    default:      g_assert_not_reached();    }}static voidstream_stock_field_get_cb (Live365Stream *stream,			   STHandlerStockField stock_field,			   GValue *value,			   gpointer data){  switch (stock_field)    {    case ST_HANDLER_STOCK_FIELD_NAME:      g_value_set_string(value, stream->title);      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->description);      break;    case ST_HANDLER_STOCK_FIELD_HOMEPAGE:      g_value_set_string(value, stream->homepage);      break;    case ST_HANDLER_STOCK_FIELD_URI_LIST:      {	GValueArray *value_array;	GValue uri_value = { 0, };	char *uri;	value_array = g_value_array_new(1);	uri = stream_get_url(stream, FALSE);	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);	break;      }    }}static voidstream_free_cb (Live365Stream *stream, gpointer data){  g_free(stream->title);  g_free(stream->genre);  g_free(stream->description);  g_free(stream->broadcaster);  g_free(stream->audio);  g_free(stream->homepage);  st_stream_free((STStream *) stream);}static char *stream_get_url (Live365Stream *stream, gboolean blocking){  char *params;  char *url;  g_return_val_if_fail(stream != NULL, NULL);  params = get_session_params(blocking);  if (params)    {      url = g_strdup_printf(LIVE365_ROOT "play/%i%s", stream->station_id, params);      g_free(params);    }  else    url = g_strdup_printf(LIVE365_ROOT "play/%i", stream->station_id);  return url;}static gbooleanstream_tune_in_cb (Live365Stream *stream, gpointer data, GError **err){  char *url;  gboolean status;  url = stream_get_url(stream, TRUE);  status = st_action_run("play-stream", url, err);  g_free(url);  return status;}static gbooleanstream_record_cb (Live365Stream *stream, gpointer data, GError **err){  char *url;  gboolean status;  url = stream_get_url(stream, TRUE);  status = st_action_run("record-stream", url, err);  g_free(url);  return status;}static gbooleanstream_browse_cb (Live365Stream *stream, gpointer data, GError **err){  return st_action_run("view-web", stream->homepage, err);}static char *get_session_params (gboolean blocking){  char *config_name;  char *config_password;  char *name = NULL;  char *password = NULL;  char *params = NULL;    if (! st_handler_config_get_boolean(live365_handler, CONFIG_USE_MEMBERSHIP))    return NULL;  config_name = st_handler_config_get_string(live365_handler, CONFIG_NAME);  config_password = st_handler_config_get_string(live365_handler, CONFIG_PASSWORD);

⌨️ 快捷键说明

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