diff options
author | Matthew Hoops | 2015-10-19 22:14:50 -0400 |
---|---|---|
committer | Johannes Schickel | 2016-03-13 13:57:30 +0100 |
commit | c6c0f527a7394d70afd4a50d8b9b41d035bbe7b8 (patch) | |
tree | cfbbe0e0b6252c704cab2de87d5bc455070b59ac | |
parent | 41a1dcb0bb8bd7aaa20d03ea92aa49210b66fa92 (diff) | |
download | scummvm-rg350-c6c0f527a7394d70afd4a50d8b9b41d035bbe7b8.tar.gz scummvm-rg350-c6c0f527a7394d70afd4a50d8b9b41d035bbe7b8.tar.bz2 scummvm-rg350-c6c0f527a7394d70afd4a50d8b9b41d035bbe7b8.zip |
BACKENDS: Switch to CDROMREADRAW for Linux audio CD
CDROMREADAUDIO seems to crash the kernel when ejecting while playing. Let's try to avoid that.
-rw-r--r-- | backends/audiocd/linux/linux-audiocd.cpp | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/backends/audiocd/linux/linux-audiocd.cpp b/backends/audiocd/linux/linux-audiocd.cpp index ea5eb1f9be..b48ce78b94 100644 --- a/backends/audiocd/linux/linux-audiocd.cpp +++ b/backends/audiocd/linux/linux-audiocd.cpp @@ -64,6 +64,20 @@ static int getFrameCount(const cdrom_msf0 &msf) { return time; } +// Helper function to convert an error code into a human-readable message +static Common::String getErrorMessage(int errorCode) { + char buf[256]; + buf[0] = 0; + +#ifdef _GNU_SOURCE + // glibc sucks + return Common::String(strerror_r(errorCode, buf, sizeof(buf))); +#else + strerror_r(errorCode, buf, sizeof(buf)); + return Common::String(buf); +#endif +} + class LinuxAudioCDStream : public AudioCDStream { public: LinuxAudioCDStream(int fd, const cdrom_tocentry &startEntry, const cdrom_tocentry &endEntry); @@ -89,23 +103,33 @@ LinuxAudioCDStream::~LinuxAudioCDStream() { } bool LinuxAudioCDStream::readFrame(int frame, int16 *buffer) { + // Create the argument + union { + cdrom_msf msf; + char buffer[kBytesPerFrame]; + } arg; + int seconds = frame / kFramesPerSecond; frame %= kFramesPerSecond; int minutes = seconds / kSecondsPerMinute; seconds %= kSecondsPerMinute; // Request to read that frame - cdrom_read_audio readAudio; - readAudio.addr.msf.minute = minutes; - readAudio.addr.msf.second = seconds; - readAudio.addr.msf.frame = frame; - readAudio.addr_format = CDROM_MSF; - readAudio.nframes = 1; - readAudio.buf = reinterpret_cast<__u8*>(buffer); - - if (ioctl(_fd, CDROMREADAUDIO, &readAudio) < 0) + // We don't use CDROMREADAUDIO, as it seems to cause kernel + // panics on ejecting discs. Probably bad to eject the disc + // while playing, but at least let's try to prevent that case. + arg.msf.cdmsf_min0 = minutes; + arg.msf.cdmsf_sec0 = seconds; + arg.msf.cdmsf_frame0 = frame; + // The "end" part is irrelevant (why isn't cdrom_msf0 the type + // instead?) + + if (ioctl(_fd, CDROMREADRAW, &arg) < 0) { + warning("Failed to CD read audio: %s", getErrorMessage(errno).c_str()); return false; + } + memcpy(buffer, arg.buffer, kBytesPerFrame); return true; } |