diff options
Diffstat (limited to 'plugins/converter/converter.c')
-rw-r--r-- | plugins/converter/converter.c | 178 |
1 files changed, 132 insertions, 46 deletions
diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c index 39604785..a653089a 100644 --- a/plugins/converter/converter.c +++ b/plugins/converter/converter.c @@ -1,6 +1,6 @@ /* DeaDBeeF - ultimate music player for GNU/Linux systems with X11 - Copyright (C) 2009-2011 Alexey Yakovenko <waker@users.sourceforge.net> + Copyright (C) 2009-2012 Alexey Yakovenko <waker@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,8 +18,10 @@ */ #include <stdlib.h> #include <string.h> +#include <sys/types.h> #include <sys/stat.h> #include <dirent.h> +#include <fcntl.h> #include <unistd.h> #include "converter.h" #include "../../deadbeef.h" @@ -27,6 +29,11 @@ #ifndef PATH_MAX #define PATH_MAX 1024 /* max # of characters in a path name */ #endif + +#ifndef __linux__ +#define O_LARGEFILE 0 +#endif + #define min(x,y) ((x)<(y)?(x):(y)) //#define trace(...) { fprintf(stderr, __VA_ARGS__); } @@ -149,6 +156,10 @@ encoder_preset_load (const char *fname) { // @return -1 on path/write error, -2 if file already exists int encoder_preset_save (ddb_encoder_preset_t *p, int overwrite) { + if (!p->title || !p->title[0]) { + fprintf (stderr, "encoder_preset_save: empty title\n"); + return -1; + } const char *confdir = deadbeef->get_config_dir (); char path[1024]; if (snprintf (path, sizeof (path), "%s/presets", confdir) < 0) { @@ -349,6 +360,10 @@ dsp_preset_load (const char *fname) { int dsp_preset_save (ddb_dsp_preset_t *p, int overwrite) { + if (!p->title || !p->title[0]) { + fprintf (stderr, "dsp_preset_save: empty title\n"); + return -1; + } const char *confdir = deadbeef->get_config_dir (); char path[1024]; if (snprintf (path, sizeof (path), "%s/presets", confdir) < 0) { @@ -639,7 +654,7 @@ get_output_field (DB_playItem_t *it, const char *field, char *out, int sz) deadbeef->pl_format_title (it, idx, out, sz, -1, field); // replace invalid chars - char invalid[] = "/\\?%*:|\"<>"; + char invalid[] = "/\\?%*:|\"<>`"; char *p = out; while (*p) { if (strchr (invalid, *p)) { @@ -650,15 +665,45 @@ get_output_field (DB_playItem_t *it, const char *field, char *out, int sz) trace ("field '%s' expanded to '%s'\n", field, out); } -static void -get_output_path (DB_playItem_t *it, const char *outfolder, const char *outfile, ddb_encoder_preset_t *encoder_preset, char *out, int sz) { +void +get_output_path (DB_playItem_t *it, const char *outfolder_user, const char *outfile, ddb_encoder_preset_t *encoder_preset, int preserve_folder_structure, const char *root_folder, int write_to_source_folder, char *out, int sz) { + + const char *uri = strdupa (deadbeef->pl_find_meta (it, ":URI")); + char outfolder_preserve[2000]; + if (preserve_folder_structure) { + // generate new outfolder + int rootlen = strlen (root_folder); + const char *e = strrchr (uri, '/'); + if (e) { + const char *s = uri + rootlen; + char subpath[e-s+1]; + memcpy (subpath, s, e-s); + subpath[e-s] = 0; + snprintf (outfolder_preserve, sizeof (outfolder_preserve), "%s/%s", outfolder_user[0] ? outfolder_user : getenv("HOME"), subpath); + } + } + + const char *outfolder; + + if (write_to_source_folder) { + char *path = strdupa (uri); + char *sep = strrchr (path, '/'); + if (sep) { + *sep = 0; + } + outfolder = path; + } + else { + outfolder = preserve_folder_structure ? outfolder_preserve : outfolder_user; + } + int l; char fname[PATH_MAX]; - char *path = outfolder[0] ? strdupa (outfolder) : strdupa (getenv("HOME")); + char *path = strdupa (outfolder); char *pattern = strdupa (outfile); // replace invalid chars - char invalid[] = "?%*:|\"<>"; + char invalid[] = "?%*:|\"<>`"; char *p = path; while (*p) { if (strchr (invalid, *p)) { @@ -693,6 +738,13 @@ get_output_path (DB_playItem_t *it, const char *outfolder, const char *outfile, trace ("converter output file is '%s'\n", out); } +static void +get_output_path_1_0 (DB_playItem_t *it, const char *outfolder, const char *outfile, ddb_encoder_preset_t *encoder_preset, char *out, int sz) { + fprintf (stderr, "converter: warning: old version of \"get_output_path\" has been called, please update your plugins which depend on converter 1.1\n"); + *out = 0; + sz = 0; +} + static int check_dir (const char *dir, mode_t mode) { @@ -709,7 +761,7 @@ check_dir (const char *dir, mode_t mode) trace ("creating dir %s\n", tmp); if (0 != mkdir (tmp, mode)) { - trace ("Failed to create %s (%d)\n", tmp, errno); + trace ("Failed to create %s\n", tmp); free (tmp); return 0; } @@ -722,7 +774,7 @@ check_dir (const char *dir, mode_t mode) } int -convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int output_bps, int output_is_float, int preserve_folder_structure, const char *root_folder, ddb_encoder_preset_t *encoder_preset, ddb_dsp_preset_t *dsp_preset, int *abort) { +convert (DB_playItem_t *it, const char *out, int output_bps, int output_is_float, ddb_encoder_preset_t *encoder_preset, ddb_dsp_preset_t *dsp_preset, int *abort) { if (deadbeef->pl_get_item_duration (it) <= 0) { deadbeef->pl_lock (); const char *fname = deadbeef->pl_find_meta (it, ":URI"); @@ -731,17 +783,11 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp return -1; } - if (!check_dir (outfolder, 0755)) { - fprintf (stderr, "converter: failed to create output folder: %s\n", outfolder); - return -1; - } - int err = -1; FILE *enc_pipe = NULL; - FILE *temp_file = NULL; + int temp_file = -1; DB_decoder_t *dec = NULL; DB_fileinfo_t *fileinfo = NULL; - char out[PATH_MAX] = ""; // full path to output file char input_file_name[PATH_MAX] = ""; dec = (DB_decoder_t *)deadbeef->plug_get_for_id (deadbeef->pl_find_meta (it, ":DECODER")); @@ -759,7 +805,16 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp output_is_float = fileinfo->fmt.is_float; } - get_output_path (it, outfolder, outfile, encoder_preset, out, sizeof (out)); + char *final_path = strdupa (out); + char *sep = strrchr (final_path, '/'); + if (sep) { + *sep = 0; + if (!check_dir (final_path, 0755)) { + fprintf (stderr, "converter: failed to create output folder: %s\n", final_path); + goto error; + } + } + if (encoder_preset->method == DDB_ENCODER_METHOD_FILE) { const char *tmp = getenv ("TMPDIR"); if (!tmp) { @@ -813,17 +868,19 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp fprintf (stderr, "converter: will encode using: %s\n", enc[0] ? enc : "internal RIFF WAVE writer"); + mode_t wrmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + if (!encoder_preset->encoder[0]) { // write to wave file - temp_file = fopen (out, "w+b"); - if (!temp_file) { + temp_file = open (out, O_LARGEFILE | O_WRONLY | O_CREAT | O_TRUNC, wrmode); + if (temp_file == -1) { fprintf (stderr, "converter: failed to open output wave file %s\n", out); goto error; } } else if (encoder_preset->method == DDB_ENCODER_METHOD_FILE) { - temp_file = fopen (input_file_name, "w+b"); - if (!temp_file) { + temp_file = open (input_file_name, O_LARGEFILE | O_WRONLY | O_CREAT | O_TRUNC, wrmode); + if (temp_file == -1) { fprintf (stderr, "converter: failed to open temp file %s\n", input_file_name); goto error; } @@ -836,8 +893,8 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp } } - if (!temp_file) { - temp_file = enc_pipe; + if (temp_file == -1 && enc_pipe) { + temp_file = fileno (enc_pipe); } // write wave header @@ -934,15 +991,21 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp memcpy (&wavehdr[32], &blockalign, 2); memcpy (&wavehdr[34], &output_bps, 2); - fwrite (wavehdr, 1, wavehdr_size, temp_file); + if (wavehdr_size != write (temp_file, wavehdr, wavehdr_size)) { + fprintf (stderr, "converter: wave header write error\n"); + goto error; + } if (encoder_preset->method == DDB_ENCODER_METHOD_PIPE) { size = 0; } - fwrite (&size, 1, sizeof (size), temp_file); + if (write (temp_file, &size, sizeof (size)) != sizeof (size)) { + fprintf (stderr, "converter: wave header size write error\n"); + goto error; + } header_written = 1; } - int64_t res = fwrite (buffer, 1, sz, temp_file); + int64_t res = write (temp_file, buffer, sz); if (sz != res) { fprintf (stderr, "converter: write error (%lld bytes written out of %d)\n", res, sz); goto error; @@ -951,12 +1014,17 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp if (abort && *abort) { goto error; } - if (temp_file && temp_file != enc_pipe) { - fseek (temp_file, wavehdr_size, SEEK_SET); - fwrite (&outsize, 1, 4, temp_file); + if (temp_file != -1 && (!enc_pipe || temp_file != fileno (enc_pipe))) { + lseek (temp_file, wavehdr_size, SEEK_SET); + if (4 != write (temp_file, &outsize, 4)) { + fprintf (stderr, "converter: data size write error\n"); + goto error; + } - fclose (temp_file); - temp_file = NULL; + if (temp_file != -1 && (!enc_pipe || temp_file != fileno (enc_pipe))) { + close (temp_file); + temp_file = -1; + } } if (encoder_preset->encoder[0] && encoder_preset->method == DDB_ENCODER_METHOD_FILE) { @@ -966,9 +1034,9 @@ convert (DB_playItem_t *it, const char *outfolder, const char *outfile, int outp } err = 0; error: - if (temp_file && temp_file != enc_pipe) { - fclose (temp_file); - temp_file = NULL; + if (temp_file != -1 && (!enc_pipe || temp_file != fileno (enc_pipe))) { + close (temp_file); + temp_file = -1; } if (enc_pipe) { pclose (enc_pipe); @@ -986,7 +1054,17 @@ error: } // write junklib tags - uint32_t tagflags = JUNK_STRIP_ID3V2 | JUNK_STRIP_APEV2 | JUNK_STRIP_ID3V1; + + DB_playItem_t *out_it = NULL; + + if (encoder_preset->tag_id3v2 || encoder_preset->tag_id3v1 || encoder_preset->tag_apev2 || encoder_preset->tag_flac || encoder_preset->tag_oggvorbis) { + out_it = deadbeef->pl_item_alloc (); + deadbeef->pl_item_copy (out_it, it); + deadbeef->pl_replace_meta (out_it, ":URI", out); + deadbeef->pl_delete_meta (out_it, "cuesheet"); + } + + uint32_t tagflags = 0; if (encoder_preset->tag_id3v2) { tagflags |= JUNK_WRITE_ID3V2; } @@ -996,12 +1074,11 @@ error: if (encoder_preset->tag_apev2) { tagflags |= JUNK_WRITE_APEV2; } - DB_playItem_t *out_it = deadbeef->pl_item_alloc (); - deadbeef->pl_item_copy (out_it, it); - deadbeef->pl_replace_meta (out_it, ":URI", out); - deadbeef->pl_delete_meta (out_it, "cuesheet"); - deadbeef->junk_rewrite_tags (out_it, tagflags, encoder_preset->id3v2_version + 3, "iso8859-1"); + if (tagflags) { + tagflags |= JUNK_STRIP_ID3V2 | JUNK_STRIP_APEV2 | JUNK_STRIP_ID3V1; + deadbeef->junk_rewrite_tags (out_it, tagflags, encoder_preset->id3v2_version + 3, "iso8859-1"); + } // write flac tags if (encoder_preset->tag_flac) { @@ -1044,14 +1121,20 @@ error: } } } - - deadbeef->pl_item_unref (out_it); - + if (out_it) { + deadbeef->pl_item_unref (out_it); + } return err; } int +convert_1_0 (DB_playItem_t *it, const char *outfolder, const char *outfile, int output_bps, int output_is_float, int preserve_folder_structure, const char *root_folder, ddb_encoder_preset_t *encoder_preset, ddb_dsp_preset_t *dsp_preset, int *abort) { + fprintf (stderr, "converter: warning: old version of \"convert\" has been called, please update your plugins which depend on converter 1.1\n"); + return -1; +} + +int converter_cmd (int cmd, ...) { return -1; } @@ -1076,14 +1159,14 @@ static ddb_converter_t plugin = { .misc.plugin.api_vmajor = 1, .misc.plugin.api_vminor = 0, .misc.plugin.version_major = 1, - .misc.plugin.version_minor = 1, + .misc.plugin.version_minor = 2, .misc.plugin.type = DB_PLUGIN_MISC, .misc.plugin.name = "Converter", .misc.plugin.id = "converter", .misc.plugin.descr = "Converts any supported formats to other formats.\n" "Requires separate GUI plugin, e.g. Converter GTK UI\n", .misc.plugin.copyright = - "Copyright (C) 2009-2011 Alexey Yakovenko <waker@users.sourceforge.net>\n" + "Copyright (C) 2009-2012 Alexey Yakovenko <waker@users.sourceforge.net>\n" "\n" "This program is free software; you can redistribute it and/or\n" "modify it under the terms of the GNU General Public License\n" @@ -1123,13 +1206,16 @@ static ddb_converter_t plugin = { .dsp_preset_append = dsp_preset_append, .dsp_preset_remove = dsp_preset_remove, .dsp_preset_replace = dsp_preset_replace, - .get_output_path = get_output_path, - .convert = convert, + .get_output_path_1_0 = get_output_path_1_0, + .convert_1_0 = convert_1_0, // 1.1 entry points .load_encoder_presets = load_encoder_presets, .load_dsp_presets = load_dsp_presets, .free_encoder_presets = free_encoder_presets, .free_dsp_presets = free_dsp_presets, + // 1.2 entry points + .convert = convert, + .get_output_path = get_output_path, }; DB_plugin_t * |