Codebase list squeezelite / 3ab9661
Merge tag 'upstream/1.6.2' into develop Tag upstream version 1.6.2 Chris Boot 9 years ago
5 changed file(s) with 78 addition(s) and 32 deletion(s). Raw diff Collapse all Expand all
7373 - fix gapless playback on portaudio builds
7474 - fix gapless playback for mp3 localfile case with tags at start of file
7575
76 Version 1.6.1
77 =============
76 Version 1.6.1 22/4/14
77 =====================
7878
7979 Minor changes
8080 - fix bug with PA version changing sample rate between tracks
8181 - fix crash when skipping in ogg while resampling
8282 - fix typo
83
84 Version 1.6.2 26/5/14
85 =====================
86
87 Minor changes
88 - fix XRUN on track change when resampling on low power cpus
89 - log command line to logfile when debugging enabled
90 - option to exclude codecs (-e)
91 - support parallel execution of libsoxr
120120
121121 static thread_type thread;
122122
123 void decode_init(log_level level, const char *opt) {
123 void decode_init(log_level level, const char *include_codecs, const char *exclude_codecs) {
124124 int i;
125125
126126 loglevel = level;
127127
128 LOG_INFO("init decode");
128 LOG_INFO("init decode, include codecs: %s exclude codecs: %s", include_codecs ? include_codecs : "", exclude_codecs);
129129
130130 // register codecs
131131 // dsf,dff,alc,wma,wmap,wmal,aac,spt,ogg,ogf,flc,aif,pcm,mp3
132132 i = 0;
133133 #if DSD
134 if (!opt || strstr(opt, "dsd")) codecs[i++] = register_dsd();
134 if (!strstr(exclude_codecs, "dsd") && (!include_codecs || strstr(include_codecs, "dsd"))) codecs[i++] = register_dsd();
135135 #endif
136136 #if FFMPEG
137 if (!opt || strstr(opt, "alac")) codecs[i++] = register_ff("alc");
138 if (!opt || strstr(opt, "wma")) codecs[i++] = register_ff("wma");
139 #endif
140 if (!opt || strstr(opt, "aac")) codecs[i++] = register_faad();
141 if (!opt || strstr(opt, "ogg")) codecs[i++] = register_vorbis();
142 if (!opt || strstr(opt, "flac")) codecs[i++] = register_flac();
143 if (!opt || strstr(opt, "pcm")) codecs[i++] = register_pcm();
137 if (!strstr(exclude_codecs, "alac") && (!include_codecs || strstr(include_codecs, "alac"))) codecs[i++] = register_ff("alc");
138 if (!strstr(exclude_codecs, "wma") && (!include_codecs || strstr(include_codecs, "wma"))) codecs[i++] = register_ff("wma");
139 #endif
140 if (!strstr(exclude_codecs, "aac") && (!include_codecs || strstr(include_codecs, "aac"))) codecs[i++] = register_faad();
141 if (!strstr(exclude_codecs, "ogg") && (!include_codecs || strstr(include_codecs, "ogg"))) codecs[i++] = register_vorbis();
142 if (!strstr(exclude_codecs, "flac") && (!include_codecs || strstr(include_codecs, "flac"))) codecs[i++] = register_flac();
143 if (!strstr(exclude_codecs, "pcm") && (!include_codecs || strstr(include_codecs, "pcm"))) codecs[i++] = register_pcm();
144144
145145 // try mad then mpg for mp3 unless command line option passed
146 if ( !opt || strstr(opt, "mp3") || strstr(opt, "mad")) codecs[i] = register_mad();
147 if ((!opt || strstr(opt, "mp3") || strstr(opt, "mpg")) && !codecs[i]) codecs[i] = register_mpg();
146 if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mad")) &&
147 (!include_codecs || strstr(include_codecs, "mp3") || strstr(include_codecs, "mad"))) codecs[i] = register_mad();
148 if (!(strstr(exclude_codecs, "mp3") || strstr(exclude_codecs, "mpg")) && !codecs[i] &&
149 (!include_codecs || strstr(include_codecs, "mp3") || strstr(include_codecs, "mpg"))) codecs[i] = register_mpg();
148150
149151 mutex_create(decode.mutex);
150152
195197
196198 unsigned decode_newstream(unsigned sample_rate, unsigned supported_rates[]) {
197199
200 // called with O locked to get sample rate for potentially processed output stream
201 // release O mutex during process_newstream as it can take some time
202
198203 MAY_PROCESS(
199204 if (decode.process) {
200 return process_newstream(&decode.direct, sample_rate, supported_rates);
205 UNLOCK_O;
206 sample_rate = process_newstream(&decode.direct, sample_rate, supported_rates);
207 LOCK_O;
201208 }
202209 );
203210
2323
2424 #define TITLE "Squeezelite " VERSION ", Copyright 2012-2014 Adrian Smith."
2525
26 #define CODECS_BASE "flac,pcm,mp3,ogg,aac"
27 #if FFMPEG
28 #define CODECS_FF ",wma,alac"
29 #else
30 #define CODECS_FF ""
31 #endif
32 #if DSD
33 #define CODECS_DSD ",dsd"
34 #else
35 #define CODECS_DSD ""
36 #endif
37 #define CODECS_MP3 " (mad,mpg for specific mp3 codec)"
38
39 #define CODECS CODECS_BASE CODECS_FF CODECS_DSD CODECS_MP3
40
2641 static void usage(const char *argv0) {
2742 printf(TITLE " See -t for license terms\n"
2843 "Usage: %s [options]\n"
4156 #endif
4257 " -a <f>\t\tSpecify sample format (16|24|32) of output file when using -o - to output samples to stdout (interleaved little endian only)\n"
4358 " -b <stream>:<output>\tSpecify internal Stream and Output buffer sizes in Kbytes\n"
44 " -c <codec1>,<codec2>\tRestrict codecs to those specified, otherwise load all available codecs; known codecs: "
45 "flac,pcm,mp3,ogg,aac"
46 #if FFMPEG
47 ",wma,alac"
48 #endif
49 #if DSD
50 ",dsd"
51 #endif
52 " (mad,mpg for specific mp3 codec)\n"
59 " -c <codec1>,<codec2>\tRestrict codecs to those specified, otherwise load all available codecs; known codecs: " CODECS "\n"
5360 " -d <log>=<level>\tSet logging level, logs: all|slimproto|stream|decode|output, level: info|debug|sdebug\n"
61 " -e <codec1>,<codec2>\tExplicitly exclude native support of one or more codecs; known codecs: " CODECS "\n"
5462 " -f <logfile>\t\tWrite debug to logfile\n"
5563 " -m <mac addr>\t\tSet mac address, format: ab:cd:ef:12:34:56\n"
5664 " -n <name>\t\tSet the player name\n"
156164 int main(int argc, char **argv) {
157165 char *server = NULL;
158166 char *output_device = "default";
159 char *codecs = NULL;
167 char *include_codecs = NULL;
168 char *exclude_codecs = "";
160169 char *name = NULL;
161170 char *namefile = NULL;
162171 char *logfile = NULL;
188197
189198 char *optarg = NULL;
190199 int optind = 1;
200 int i;
201
202 #define MAXCMDLINE 256
203 char cmdline[MAXCMDLINE] = "";
191204
192205 get_mac(mac);
206
207 for (i = 0; i < argc && (strlen(argv[i]) + strlen(cmdline) + 2 < MAXCMDLINE); i++) {
208 strcat(cmdline, argv[i]);
209 strcat(cmdline, " ");
210 }
193211
194212 while (optind < argc && strlen(argv[optind]) >= 2 && argv[optind][0] == '-') {
195213 char *opt = argv[optind] + 1;
196 if (strstr("oabcdfmnNprs", opt) && optind < argc - 1) {
214 if (strstr("oabcdefmnNprs", opt) && optind < argc - 1) {
197215 optarg = argv[optind + 1];
198216 optind += 2;
199217 } else if (strstr("ltz"
230248 }
231249 break;
232250 case 'c':
233 codecs = optarg;
251 include_codecs = optarg;
252 break;
253 case 'e':
254 exclude_codecs = optarg;
234255 break;
235256 case 'd':
236257 {
398419 }
399420
400421 if (logfile) {
401 if (!freopen(logfile, "a", stdout) || !freopen(logfile, "a", stderr)) {
422 if (!freopen(logfile, "a", stderr)) {
402423 fprintf(stderr, "error opening logfile %s: %s\n", logfile, strerror(errno));
424 } else {
425 if (log_output >= lINFO || log_stream >= lINFO || log_decode >= lINFO || log_slimproto >= lINFO) {
426 fprintf(stderr, "\n%s\n", cmdline);
427 }
403428 }
404429 }
405430
438463 }
439464 #endif
440465
441 decode_init(log_decode, codecs);
466 decode_init(log_decode, include_codecs, exclude_codecs);
442467
443468 #if RESAMPLE
444469 if (resample) {
4949 void (* soxr_delete)(soxr_t);
5050 soxr_error_t (* soxr_process)(soxr_t, soxr_in_t, size_t, size_t *, soxr_out_t, size_t olen, size_t *);
5151 size_t *(* soxr_num_clips)(soxr_t);
52 soxr_runtime_spec_t (* soxr_runtime_spec)(unsigned num_threads);
5253 // soxr_strerror is a macro so not included here
5354 #endif
5455 };
174175
175176 soxr_io_spec_t io_spec;
176177 soxr_quality_spec_t q_spec;
178 soxr_runtime_spec_t r_spec;
177179 soxr_error_t error;
178180
179181 LOG_INFO("resampling from %u -> %u", raw_sample_rate, outrate);
195197 q_spec.phase_response = r->q_phase_response;
196198 }
197199
200 r_spec = SOXR(r, runtime_spec, 0); // make use of libsoxr OpenMP support allowing parallel execution if multiple cores
201
198202 LOG_DEBUG("resampling with soxr_quality_spec_t[precision: %03.1f, passband_end: %03.6f, stopband_begin: %03.6f, "
199203 "phase_response: %03.1f, flags: 0x%02x], soxr_io_spec_t[scale: %03.2f]", q_spec.precision,
200204 q_spec.passband_end, q_spec.stopband_begin, q_spec.phase_response, q_spec.flags, io_spec.scale);
201205
202 r->resampler = SOXR(r, create, raw_sample_rate, outrate, 2, &error, &io_spec, &q_spec, NULL);
206 r->resampler = SOXR(r, create, raw_sample_rate, outrate, 2, &error, &io_spec, &q_spec, &r_spec);
203207 if (error) {
204208 LOG_INFO("soxr_create error: %s", soxr_strerror(error));
205209 return false;
234238
235239 r->soxr_io_spec = dlsym(handle, "soxr_io_spec");
236240 r->soxr_quality_spec = dlsym(handle, "soxr_quality_spec");
241 r->soxr_runtime_spec = dlsym(handle, "soxr_runtime_spec");
237242 r->soxr_create = dlsym(handle, "soxr_create");
238243 r->soxr_delete = dlsym(handle, "soxr_delete");
239244 r->soxr_process = dlsym(handle, "soxr_process");
1919
2020 // make may define: PORTAUDIO, SELFPIPE, RESAMPLE, VISEXPORT, DSD, LINKALL to influence build
2121
22 #define VERSION "v1.6.1"
22 #define VERSION "v1.6.2"
2323
2424 // build detection
2525 #if defined(linux)
465465 decode_state (*decode)(void);
466466 };
467467
468 void decode_init(log_level level, const char *opt);
468 void decode_init(log_level level, const char *include_codecs, const char *exclude_codecs);
469469 void decode_close(void);
470470 void decode_flush(void);
471471 unsigned decode_newstream(unsigned sample_rate, unsigned supported_rates[]);