diff options
Diffstat (limited to 'src/input/input_cdda.c')
-rw-r--r-- | src/input/input_cdda.c | 247 |
1 files changed, 88 insertions, 159 deletions
diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index d21c8e4db..0e378c299 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -15,12 +15,10 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Compact Disc Digital Audio (CDDA) Input Plugin * by Mike Melanson (melanson@pcisys.net) - * - * $Id: input_cdda.c,v 1.94 2007/03/10 00:48:59 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -41,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> @@ -55,6 +56,8 @@ #include <netinet/in.h> #include <sys/socket.h> +#include <basedir.h> + #define LOG_MODULE "input_cdda" #define LOG_VERBOSE /* @@ -62,10 +65,9 @@ */ #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) @@ -128,7 +130,6 @@ typedef struct { int enabled; char *server; int port; - char *cache_dir; char *cdiscid; char *disc_title; @@ -381,10 +382,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__) @@ -420,10 +421,9 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -531,10 +531,9 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -614,15 +613,18 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f return 0; } -#elif defined(__FreeBSD__) || defined(__NetBSD__) +#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) #include <sys/cdio.h> + +#ifdef HAVE_SYS_SCSIIO_H #include <sys/scsiio.h> +#endif static int read_cdrom_toc(int fd, cdrom_toc *toc) { struct ioc_toc_header tochdr; -#if defined(__FreeBSD__) +#if defined(__FreeBSD_kernel__) struct ioc_read_toc_single_entry tocentry; #elif defined(__NetBSD__) struct ioc_read_toc_entry tocentry; @@ -641,10 +643,9 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -653,7 +654,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { memset(&tocentry, 0, sizeof(tocentry)); -#if defined(__FreeBSD__) +#if defined(__FreeBSD_kernel__) tocentry.track = i; tocentry.address_format = CD_MSF_FORMAT; if (ioctl(fd, CDIOREADTOCENTRY, &tocentry) == -1) { @@ -672,7 +673,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { } #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD_kernel__) toc->toc_entries[i-1].track_mode = (tocentry.entry.control & 0x04) ? 1 : 0; toc->toc_entries[i-1].first_frame_minute = tocentry.entry.addr.msf.minute; toc->toc_entries[i-1].first_frame_second = tocentry.entry.addr.msf.second; @@ -696,7 +697,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { /* fetch the leadout as well */ memset(&tocentry, 0, sizeof(tocentry)); -#if defined(__FreeBSD__) +#if defined(__FreeBSD_kernel__) tocentry.track = CD_LEADOUT_TRACK; tocentry.address_format = CD_MSF_FORMAT; if (ioctl(fd, CDIOREADTOCENTRY, &tocentry) == -1) { @@ -715,7 +716,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { } #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD_kernel__) toc->leadout_track.track_mode = (tocentry.entry.control & 0x04) ? 1 : 0; toc->leadout_track.first_frame_minute = tocentry.entry.addr.msf.minute; toc->leadout_track.first_frame_second = tocentry.entry.addr.msf.second; @@ -744,8 +745,8 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f int fd = this_gen->fd; while( num_frames ) { -#if defined(__FreeBSD__) -#if __FreeBSD_version < 501106 +#if defined(__FreeBSD_kernel__) +#if __FreeBSD_kernel_version < 501106 struct ioc_read_audio cdda; cdda.address_format = CD_MSF_FORMAT; @@ -754,13 +755,10 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f cdda.address.msf.frame = frame % CD_FRAMES_PER_SECOND; cdda.nframes = 1; cdda.buffer = data; -#endif - -#if __FreeBSD_version >= 501106 - if (pread(fd, data, CD_RAW_FRAME_SIZE, frame * CD_RAW_FRAME_SIZE) != CD_RAW_FRAME_SIZE) { -#else /* read a frame */ if(ioctl(fd, CDIOCREADAUDIO, &cdda) < 0) { +#else + if (pread(fd, data, CD_RAW_FRAME_SIZE, frame * CD_RAW_FRAME_SIZE) != CD_RAW_FRAME_SIZE) { #endif perror("CDIOCREADAUDIO"); return -1; @@ -837,10 +835,9 @@ static int read_cdrom_toc(cdda_input_plugin_t *this_gen, cdrom_toc *toc) { /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -988,11 +985,8 @@ static int parse_url (char *urlbuf, char** host, int *port) { } #endif -static int -#ifdef __GNUC__ -__attribute__((format (printf, 4, 5))) -#endif -network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, ...) +static int XINE_FORMAT_PRINTF(4, 5) +network_command( xine_stream_t *stream, int socket, void *data_buf, const char *msg, ...) { char buf[_BUFSIZ]; va_list args; @@ -1041,13 +1035,13 @@ network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, . #ifndef WIN32 -static int network_connect(xine_stream_t *stream, char *url ) +static int network_connect(xine_stream_t *stream, const char *_url ) { char *host; int port; int fd; - url = strdup(url); + char *url = strdup(_url); parse_url(url, &host, &port); if( !host || !strlen(host) || !port ) @@ -1086,10 +1080,9 @@ static int network_read_cdrom_toc(xine_stream_t *stream, int fd, cdrom_toc *toc) toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -1187,15 +1180,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; @@ -1298,54 +1282,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 - - int 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); - } - } -} + char buf[strlen (path) + 1]; + strcpy (buf, path); + char *p = strchr (buf, '/') ? : buf; -/* - * 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())); - - return buf; + do + { + while (*p++ == '/') /**/; + p = strchr (p, '/'); + if (p) + *p = 0; + _cdda_mkdir_safe (xine, buf); + if (p) + *p = '/'; + } while (p); } /* @@ -1447,22 +1404,24 @@ static int _cdda_cddb_handle_code(char *buf) { * 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]; + char *cdir = NULL; DIR *dir; + const char *const xdg_cache_home = xdgCacheHome(this->stream->xine->basedir_handle); + if(this == NULL) return 0; - memset(&cdir, 0, sizeof(cdir)); - snprintf(cdir, sizeof(cdir), "%s", this->cddb.cache_dir); - + cdir = alloca(strlen(xdg_cache_home) + sizeof("/"PACKAGE"/cddb")); + strcpy(cdir, xdg_cache_home); + strcat(cdir, "/"PACKAGE"/cddb"); + if((dir = opendir(cdir)) != NULL) { struct dirent *pdir; while((pdir = readdir(dir)) != NULL) { char discid[9]; - memset(&discid, 0, sizeof(discid)); snprintf(discid, sizeof(discid), "%08lx", this->cddb.disc_id); if(!strcasecmp(pdir->d_name, discid)) { @@ -1579,20 +1538,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)); + /* 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 "~/.xine/cddbcache" exist */ - snprintf(cfile, sizeof(cfile), "%s", this->cddb.cache_dir); - + /* Ensure the cache directory exists */ _cdda_mkdir_recursive_safe(this->stream->xine, cfile); - snprintf(cfile, sizeof(cfile), "%s/%08lx", this->cddb.cache_dir, this->cddb.disc_id); + sprintf(cfile, "%s/%08lx", cfile, this->cddb.disc_id); if((fd = fopen(cfile, "w")) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, @@ -1665,7 +1627,7 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { this->cddb.fd = _cdda_cddb_socket_open(this); if(this->cddb.fd >= 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("input_cdda: successfuly connected to cddb server '%s:%d'.\n"), + _("input_cdda: successfully connected to cddb server '%s:%d'.\n"), this->cddb.server, this->cddb.port); } else { @@ -1973,7 +1935,7 @@ static void _cdda_cdindex(cdda_input_plugin_t *this, cdrom_toc *toc) { sha_final(digest, &sha); - base64 = rfc822_binary(digest, 20, &size); + base64 = xine_rfc822_binary(digest, 20, &size); base64[size] = 0; _x_meta_info_set_utf8(this->stream, XINE_META_INFO_CDINDEX_DISCID, base64); @@ -2001,26 +1963,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); } } @@ -2253,7 +2204,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) { /* only allow reading in block-sized chunks */ @@ -2370,8 +2321,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; @@ -2463,7 +2413,7 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { if(this->cddb.num_tracks) { int t; - this->cddb.track = (trackinfo_t *) xine_xmalloc(sizeof(trackinfo_t) * this->cddb.num_tracks); + this->cddb.track = (trackinfo_t *) xine_xcalloc(this->cddb.num_tracks, sizeof(trackinfo_t)); for(t = 0; t < this->cddb.num_tracks; t++) { int length = (toc->toc_entries[t].first_frame_minute * CD_SECONDS_PER_MINUTE + @@ -2608,7 +2558,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; @@ -2689,24 +2639,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; @@ -2715,7 +2653,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 @@ -2743,8 +2680,8 @@ 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.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; @@ -2784,14 +2721,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"), @@ -2812,7 +2741,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 } }; |