diff options
Diffstat (limited to 'src/input/input_cdda.c')
-rw-r--r-- | src/input/input_cdda.c | 351 |
1 files changed, 98 insertions, 253 deletions
diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index 4da456384..08229874c 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -39,6 +39,9 @@ #include <sys/stat.h> #include <fcntl.h> #include <errno.h> +#ifdef HAVE_ALLOCA_H +# include <alloca.h> +#endif #ifdef HAVE_SYS_IOCTL_H # include <sys/ioctl.h> @@ -54,17 +57,29 @@ #include <netinet/in.h> #include <sys/socket.h> +#include <basedir.h> + +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <base64.h> +# include <sha1.h> +#else +# include <libavutil/base64.h> +# ifdef HAVE_LIBAVUTIL_SHA_H +# include <libavutil/sha.h> +# else +# include <libavutil/sha1.h> +# endif +#endif + #define LOG_MODULE "input_cdda" #define LOG_VERBOSE /* #define LOG */ -#include "sha1.h" -#include "base64.h" -#include "xine_internal.h" -#include "xineutils.h" -#include "input_plugin.h" +#include <xine/xine_internal.h> +#include <xine/xineutils.h> +#include <xine/input_plugin.h> #include "media_helper.h" #if defined(__sun) @@ -89,6 +104,15 @@ #define CD_LEADOUT_TRACK 0xAA #define CD_BLOCK_OFFSET 150 +#if !defined(HAVE_LIBAVUTIL_SHA_H) +/* old libavutil/sha1.h was found... */ +#define AVSHA AVSHA1 +# define av_sha_init(c,b) av_sha1_init(c) +# define av_sha_update av_sha1_update +# define av_sha_final av_sha1_final +# define av_sha_size av_sha1_size +#endif + typedef struct _cdrom_toc_entry { int track_mode; int first_frame; @@ -129,7 +153,6 @@ typedef struct { int enabled; char *server; int port; - char *cache_dir; char *cdiscid; char *disc_title; @@ -382,10 +405,10 @@ static cdrom_toc * init_cdrom_toc(void) { static void free_cdrom_toc(cdrom_toc *toc) { - if(toc && toc->toc_entries) + if ( toc ) { free(toc->toc_entries); - if (toc) - free (toc); + free(toc); + } } #if defined (__linux__) @@ -986,7 +1009,7 @@ static int parse_url (char *urlbuf, char** host, int *port) { #endif static int XINE_FORMAT_PRINTF(4, 5) -network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, ...) +network_command( xine_stream_t *stream, int socket, void *data_buf, const char *msg, ...) { char buf[_BUFSIZ]; va_list args; @@ -1037,11 +1060,11 @@ network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, . #ifndef WIN32 static int network_connect(xine_stream_t *stream, const char *got_url ) { - char *host, *url; + char *host; int port; int fd; - url = strdup(got_url); + char *url = strdup(got_url); parse_url(url, &host, &port); if( !host || !strlen(host) || !port ) @@ -1180,15 +1203,6 @@ static void port_changed_cb(void *data, xine_cfg_entry_t *cfg) { this->cddb.port = cfg->num_value; } } -static void cachedir_changed_cb(void *data, xine_cfg_entry_t *cfg) { - cdda_input_class_t *class = (cdda_input_class_t *) data; - - if(class->ip) { - cdda_input_plugin_t *this = class->ip; - - this->cddb.cache_dir = cfg->str_value; - } -} #ifdef CDROM_SELECT_SPEED static void speed_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; @@ -1291,51 +1305,27 @@ static void _cdda_mkdir_safe(xine_t *xine, char *path) { } /* - * Make recursive directory creation + * Make recursive directory creation (given an absolute pathname) */ -static void _cdda_mkdir_recursive_safe(xine_t *xine, char *path) { - char *p, *pp; - char buf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; - char buf2[XINE_PATH_MAX + XINE_NAME_MAX + 1]; - - if(path == NULL) +static void _cdda_mkdir_recursive_safe (xine_t *xine, char *path) +{ + if (!path) return; - memset(&buf, 0, sizeof(buf)); - memset(&buf2, 0, sizeof(buf2)); - - snprintf(buf, sizeof(buf), "%s", path); - pp = buf; - while((p = xine_strsep(&pp, "/")) != NULL) { - if(p && strlen(p)) { - -#ifdef WIN32 - if (*buf2 != '\0') { -#endif - size_t size = strlen(buf2); - snprintf(buf2 + size, sizeof(buf2) - size, "/%s", p); -#ifdef WIN32 - } - else { - snprintf(buf2, sizeof(buf2), "%s", p); - } -#endif /* WIN32 */ - - _cdda_mkdir_safe(xine, buf2); - } - } -} - -/* - * Where, by default, cddb cache files will be saved - */ -static char *_cdda_cddb_get_default_location(void) { - static char buf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; - - memset(&buf, 0, sizeof(buf)); - snprintf(buf, sizeof(buf), "%s/.xine/cddbcache", (xine_get_homedir())); + char buf[strlen (path) + 1]; + strcpy (buf, path); + char *p = strchr (buf, '/') ? : buf; - return buf; + do + { + while (*p++ == '/') /**/; + p = strchr (p, '/'); + if (p) + *p = 0; + _cdda_mkdir_safe (xine, buf); + if (p) + *p = '/'; + } while (p); } /* @@ -1504,14 +1494,16 @@ static void _cdda_parse_cddb_info (cdda_input_plugin_t *this, char *buffer, char * Try to load cached cddb infos */ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { - char cdir[XINE_PATH_MAX + XINE_NAME_MAX + 1]; - size_t cdir_size = 0; DIR *dir; + const char *const xdg_cache_home = xdgCacheHome(&this->stream->xine->basedir_handle); + if(this == NULL) return 0; - cdir_size = snprintf(cdir, sizeof(cdir), "%s", this->cddb.cache_dir); + const size_t cdir_size = strlen(xdg_cache_home) + sizeof("/"PACKAGE"/cddb") + 10 + 1; + char *const cdir = alloca(cdir_size); + sprintf(cdir, "%s/" PACKAGE "/cddb", xdg_cache_home); if((dir = opendir(cdir)) != NULL) { struct dirent *pdir; @@ -1524,7 +1516,7 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { if(!strcasecmp(pdir->d_name, discid)) { FILE *fd; - cdir_size += snprintf(cdir + cdir_size, sizeof(cdir) - cdir_size, "/%s", discid); + snprintf(cdir + cdir_size - 12, 10, "/%s", discid); if((fd = fopen(cdir, "r")) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: fopen(%s) failed: %s.\n", cdir, strerror(errno)); @@ -1563,20 +1555,23 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { * Save cddb grabbed infos. */ static void _cdda_save_cached_cddb_infos(cdda_input_plugin_t *this, char *filecontent) { - char cfile[XINE_PATH_MAX + XINE_NAME_MAX + 1]; FILE *fd; + char *cfile; + + const char *const xdg_cache_home = xdgCacheHome(&this->stream->xine->basedir_handle); if((this == NULL) || (filecontent == NULL)) return; - memset(&cfile, 0, sizeof(cfile)); - - /* Ensure "~/.xine/cddbcache" exist */ - snprintf(cfile, sizeof(cfile), "%s", this->cddb.cache_dir); + /* the filename is always 8 characters */ + cfile = alloca(strlen(xdg_cache_home) + sizeof("/"PACKAGE"/cddb") + 9); + strcpy(cfile, xdg_cache_home); + strcat(cfile, "/"PACKAGE"/cddb"); + /* Ensure the cache directory exists */ _cdda_mkdir_recursive_safe(this->stream->xine, cfile); - snprintf(cfile, sizeof(cfile), "%s/%08" PRIx32 , this->cddb.cache_dir, this->cddb.disc_id); + sprintf(cfile, "%s/%08" PRIx32, cfile, this->cddb.disc_id); if((fd = fopen(cfile, "w")) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, @@ -1855,39 +1850,42 @@ static uint32_t _cdda_calc_cddb_id(cdda_input_plugin_t *this) { */ static void _cdda_cdindex(cdda_input_plugin_t *this, cdrom_toc *toc) { char temp[10]; - SHA_INFO sha; - unsigned char digest[33], *base64; + struct AVSHA *sha_ctx = malloc(av_sha_size); + unsigned char digest[20]; + /* We're going to encode 20 bytes in base64, which will become + * 6 * 32 / 8 = 24 bytes. + * libavutil's base64 encoding functions, though, wants the size to + * be at least len * 4 / 3 + 12, so let's use 39. + */ + char base64[39]; int i; - unsigned long size; - sha_init(&sha); + av_sha_init(sha_ctx, 160); sprintf(temp, "%02X", toc->first_track); - sha_update(&sha, (unsigned char*) temp, strlen(temp)); + av_sha_update(sha_ctx, (unsigned char*) temp, strlen(temp)); sprintf(temp, "%02X", toc->last_track - toc->ignore_last_track); - sha_update(&sha, (unsigned char*) temp, strlen(temp)); + av_sha_update(sha_ctx, (unsigned char*) temp, strlen(temp)); sprintf (temp, "%08X", toc->leadout_track.first_frame);// + 150); - sha_update(&sha, (unsigned char*) temp, strlen(temp)); + av_sha_update(sha_ctx, (unsigned char*) temp, strlen(temp)); for (i = toc->first_track; i <= toc->last_track - toc->ignore_last_track; i++) { sprintf(temp, "%08X", toc->toc_entries[i - 1].first_frame); - sha_update(&sha, (unsigned char*) temp, strlen(temp)); + av_sha_update(sha_ctx, (unsigned char*) temp, strlen(temp)); } for (i = toc->last_track - toc->ignore_last_track + 1; i < 100; i++) { - sha_update(&sha, (unsigned char*) temp, strlen(temp)); + av_sha_update(sha_ctx, (unsigned char*) temp, strlen(temp)); } - sha_final(digest, &sha); + av_sha_final(sha_ctx, digest); + free(sha_ctx); - base64 = rfc822_binary(digest, 20, &size); - base64[size] = 0; + av_base64_encode(base64, 39, digest, 20); _x_meta_info_set_utf8(this->stream, XINE_META_INFO_CDINDEX_DISCID, base64); - - free (base64); } /* @@ -1910,26 +1908,15 @@ static void _cdda_free_cddb_info(cdda_input_plugin_t *this) { int t; for(t = 0; t < this->cddb.num_tracks; t++) { - if(this->cddb.track[t].title) - free(this->cddb.track[t].title); + free(this->cddb.track[t].title); } free(this->cddb.track); - - if(this->cddb.cdiscid) - free(this->cddb.cdiscid); - - if(this->cddb.disc_title) - free(this->cddb.disc_title); - - if(this->cddb.disc_artist) - free(this->cddb.disc_artist); - - if(this->cddb.disc_category) - free(this->cddb.disc_category); - - if(this->cddb.disc_year) - free(this->cddb.disc_year); + free(this->cddb.cdiscid); + free(this->cddb.disc_title); + free(this->cddb.disc_artist); + free(this->cddb.disc_category); + free(this->cddb.disc_year); } } @@ -2162,7 +2149,7 @@ static uint32_t cdda_plugin_get_capabilities (input_plugin_t *this_gen) { } -static off_t cdda_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { +static off_t cdda_plugin_read (input_plugin_t *this_gen, void *buf, off_t len) { cdda_input_plugin_t *this = (cdda_input_plugin_t *) this_gen; int err = 0; @@ -2283,8 +2270,7 @@ static void cdda_plugin_dispose (input_plugin_t *this_gen ) { free(this->mrl); - if (this->cdda_device) - free(this->cdda_device); + free(this->cdda_device); if (this->class) { cdda_input_class_t *inp = (cdda_input_class_t *) this->class; inp->ip = NULL; @@ -2450,127 +2436,6 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { return 1; } -static xine_mrl_t** cdda_class_get_dir(input_class_t *this_gen, - const char *filename, - int *num_files) { - cdda_input_class_t *this = (cdda_input_class_t *) this_gen; - cdda_input_plugin_t *ip; - cdrom_toc *toc; - char *base_mrl; - int len, frame; - const char * device; - int fd, i, err = -1; - int num_tracks; - - if (filename && *filename) { - device = filename; - if (strncasecmp(device,"cdda:/",6) == 0) { - device += 6; - while ('/' == *device) - device++; - device--; - } - } - else { - device = this->cdda_device; - } - lprintf("cdda_class_get_dir for >%s<\n", device); - - /* get the CD TOC */ - toc = init_cdrom_toc(); - - fd = -1; - - /* we create a new instance because getting a directory of a cd - * should not affect another cd that might be playing. */ - ip = (cdda_input_plugin_t *)xine_xmalloc(sizeof(cdda_input_plugin_t)); - ip->stream = NULL; - ip->fd = -1; - ip->net_fd = -1; - -#ifndef WIN32 - if( strchr(device,':') ) { - fd = network_connect(ip->stream, device); - if( fd != -1 ) { - err = network_read_cdrom_toc(ip->stream, fd, toc); - } - } -#endif - - if (fd == -1) { - if (cdda_open(ip, device, toc, &fd) == -1) { - lprintf("cdda_class_get_dir: opening >%s< failed %s\n", - device, strerror(errno)); - free(ip); - return NULL; - } - -#ifndef WIN32 - err = read_cdrom_toc(fd, toc); -#else - err = read_cdrom_toc(ip, toc); -#endif /* WIN32 */ - } - -#ifdef LOG - print_cdrom_toc(toc); -#endif - - cdda_close(ip); - - if ( err < 0 ) { - free(ip); - return NULL; - } - - num_tracks = toc->last_track - toc->first_track + 1; - - /* this could be done in read_cdrom_toc, but it seems other code doesn't use it */ - frame = toc->leadout_track.first_frame; - for ( i = num_tracks-1 ; i >= 0 ; i--) { - toc->toc_entries[i].total_frames = frame - toc->toc_entries[i].first_frame; - frame = toc->toc_entries[i].first_frame; - } - - if (toc->ignore_last_track) - num_tracks--; - - len = strlen(device) + 5; - base_mrl = xine_xmalloc(len+1); - sprintf(base_mrl, "cdda:%s", device); - - /* allocate space for the mrls's if needed. */ - if (num_tracks+1 > this->mrls_allocated_entries) { - this->mrls = realloc(this->mrls, (num_tracks+1) * sizeof(xine_mrl_t*)); - } - for (i = 0 ; i < num_tracks ; i++) { - if (i < this->mrls_allocated_entries) { - MRL_ZERO(this->mrls[i]); - } - else { - this->mrls[i] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); - this->mrls[i]->link = NULL; - this->mrls_allocated_entries++; - } - this->mrls[i]->origin = strdup(base_mrl); - this->mrls[i]->mrl = xine_xmalloc(len+4); - sprintf( this->mrls[i]->mrl, "%s/%d", base_mrl, i+toc->first_track); - this->mrls[i]->type = mrl_cda | mrl_file_blockdev; - this->mrls[i]->size = toc->toc_entries[i].total_frames * CD_RAW_FRAME_SIZE; - } - /* Clean up */ - while(this->mrls_allocated_entries > num_tracks) { - MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]); - free(this->mrls[this->mrls_allocated_entries--]); - } - free_cdrom_toc(toc); - free(ip); - - this->mrls[num_tracks] = NULL; - *num_files = num_tracks; - return this->mrls; -} - static void free_autoplay_list(cdda_input_class_t *this) { /* free old playlist */ @@ -2673,7 +2538,7 @@ static input_plugin_t *cdda_class_get_instance (input_class_t *cls_gen, xine_str cdda_input_plugin_t *this; cdda_input_class_t *class = (cdda_input_class_t *) cls_gen; int track; - xine_cfg_entry_t enable_entry, server_entry, port_entry, cachedir_entry; + xine_cfg_entry_t enable_entry, server_entry, port_entry; char *cdda_device = NULL; int cddb_error = class->cddb_error; @@ -2754,24 +2619,12 @@ static input_plugin_t *cdda_class_get_instance (input_class_t *cls_gen, xine_str &port_entry)) port_changed_cb(class, &port_entry); - if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_cachedir", - &cachedir_entry)) - cachedir_changed_cb(class, &cachedir_entry); - class->cddb_error = cddb_error; return (input_plugin_t *)this; } -static const char *cdda_class_get_identifier (input_class_t *this_gen) { - return "cdda"; -} - -static const char *cdda_class_get_description (input_class_t *this_gen) { - return _("CD Digital Audio (aka. CDDA)"); -} - static void cdda_class_dispose (input_class_t *this_gen) { cdda_input_class_t *this = (cdda_input_class_t *) this_gen; config_values_t *config = this->xine->config; @@ -2780,7 +2633,6 @@ static void cdda_class_dispose (input_class_t *this_gen) { config->unregister_callback(config, "media.audio_cd.use_cddb"); config->unregister_callback(config, "media.audio_cd.cddb_server"); config->unregister_callback(config, "media.audio_cd.cddb_port"); - config->unregister_callback(config, "media.audio_cd.cddb_cachedir"); #ifdef CDROM_SELECT_SPEED config->unregister_callback(config, "media.audio_cd.drive_slowdown"); #endif @@ -2815,9 +2667,10 @@ static void *init_plugin (xine_t *xine, void *data) { config = xine->config; this->input_class.get_instance = cdda_class_get_instance; - this->input_class.get_identifier = cdda_class_get_identifier; - this->input_class.get_description = cdda_class_get_description; - this->input_class.get_dir = cdda_class_get_dir; + this->input_class.identifier = "cdda"; + this->input_class.description = N_("CD Digital Audio (aka. CDDA)"); + /* this->input_class.get_dir = cdda_class_get_dir; */ + this->input_class.get_dir = NULL; this->input_class.get_autoplay_list = cdda_class_get_autoplay_list; this->input_class.dispose = cdda_class_dispose; this->input_class.eject_media = cdda_class_eject_media; @@ -2855,14 +2708,6 @@ static void *init_plugin (xine_t *xine, void *data) { "title and track information from."), XINE_CONFIG_SECURITY, port_changed_cb, (void *) this); - config->register_filename(config, "media.audio_cd.cddb_cachedir", - (_cdda_cddb_get_default_location()), XINE_CONFIG_STRING_IS_DIRECTORY_NAME, - _("CDDB cache directory"), _("The replies from the CDDB server will be " - "cached in this directory.\nThis setting is security critical, because files " - "with uncontrollable names will be created in this directory. Be sure to use " - "a dedicated directory not used for anything but CDDB caching."), XINE_CONFIG_SECURITY, - cachedir_changed_cb, (void *) this); - #ifdef CDROM_SELECT_SPEED config->register_num(config, "media.audio_cd.drive_slowdown", 4, _("slow down disc drive to this speed factor"), @@ -2883,7 +2728,7 @@ static void *init_plugin (xine_t *xine, void *data) { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "CD", XINE_VERSION_CODE, NULL, init_plugin }, + { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 18, "CD", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |