summaryrefslogtreecommitdiff
path: root/src/input/input_cdda.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/input_cdda.c')
-rw-r--r--src/input/input_cdda.c355
1 files changed, 100 insertions, 255 deletions
diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c
index 4da456384..6f6f23ef2 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 */
@@ -2586,7 +2451,7 @@ static void free_autoplay_list(cdda_input_class_t *this)
}
}
-static char ** cdda_class_get_autoplay_list (input_class_t *this_gen,
+static const char * const * cdda_class_get_autoplay_list (input_class_t *this_gen,
int *num_files) {
cdda_input_class_t *this = (cdda_input_class_t *) this_gen;
@@ -2664,7 +2529,7 @@ static char ** cdda_class_get_autoplay_list (input_class_t *this_gen,
free_cdrom_toc(toc);
if (ip != this->ip) free(ip);
- return this->autoplaylist;
+ return (const char * const *)this->autoplaylist;
}
static input_plugin_t *cdda_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream,
@@ -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 }
};