diff --git a/NEWS b/NEWS index dcd7869ff..1a9840bdf 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.23.9 (not yet released) +* input + - cdio_paranoia: add options "mode" and "skip" * decoder - ffmpeg: support FFmpeg 5.1 * output diff --git a/doc/plugins.rst b/doc/plugins.rst index 5216a9b4d..0aa36dac8 100644 --- a/doc/plugins.rst +++ b/doc/plugins.rst @@ -206,6 +206,11 @@ Plays audio CDs using libcdio. The URI has the form: "cdda://[DEVICE][/TRACK]". - If the CD drive does not specify a byte order, MPD assumes it is the CPU's native byte order. This setting allows overriding this. * - **speed N** - Request CDParanoia cap the extraction speed to Nx normal CD audio rotation speed, keeping the drive quiet. + * - **mode disable|overlap|full** + - Set the paranoia mode; ``disable`` means no fixups, ``overlap`` + performs overlapped reads, and ``full`` enables all options. + * - **skip yes|no** + - If set to ``no``, then never skip failed reads. curl ---- diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index 5a7442f26..b60490ec0 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -50,6 +50,9 @@ static constexpr Domain cdio_domain("cdio"); static bool default_reverse_endian; static unsigned speed = 0; +/* Default to full paranoia, but allow skipping sectors. */ +static int mode_flags = PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP; + class CdioParanoiaInputStream final : public InputStream { cdrom_drive_t *const drv; CdIo_t *const cdio; @@ -70,9 +73,7 @@ class CdioParanoiaInputStream final : public InputStream { lsn_from(_lsn_from), buffer_lsn(-1) { - /* Set reading mode for full paranoia, but allow - skipping sectors. */ - para.SetMode(PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP); + para.SetMode(mode_flags); /* seek to beginning of the track */ para.Seek(lsn_from); @@ -117,6 +118,26 @@ input_cdio_init(EventLoop &, const ConfigBlock &block) value); } speed = block.GetBlockValue("speed",0U); + + if (const auto *param = block.GetBlockParam("mode")) { + param->With([](const char *s){ + if (StringIsEqual(s, "disable")) + mode_flags = PARANOIA_MODE_DISABLE; + else if (StringIsEqual(s, "overlap")) + mode_flags = PARANOIA_MODE_OVERLAP; + else if (StringIsEqual(s, "full")) + mode_flags = PARANOIA_MODE_FULL; + else + throw std::invalid_argument{"Invalid paranoia mode"}; + }); + } + + if (const auto *param = block.GetBlockParam("skip")) { + if (param->GetBoolValue()) + mode_flags &= ~PARANOIA_MODE_NEVERSKIP; + else + mode_flags |= PARANOIA_MODE_NEVERSKIP; + } } struct CdioUri {