From 84d35e8212685958a05ef8f0a202bb4ce0b2a5d2 Mon Sep 17 00:00:00 2001 From: Jan Hambrecht Date: Thu, 4 Jan 2024 23:56:24 +0100 Subject: [PATCH] Support playing Audio CD from menu Add support to play an audio CD from the 'Play Optical Disc' menu. The media monitor callback function was extended by a 'forcePlayback' parameter which will override the auto play option for some of the media handlers when started explicitly by the user via the menu. --- mythplugins/mythmusic/mythmusic/mythmusic.cpp | 10 ++-- mythtv/libs/libmyth/mythmediamonitor.cpp | 11 ++-- mythtv/libs/libmyth/mythmediamonitor.h | 10 ++-- mythtv/programs/mythfrontend/mythfrontend.cpp | 56 +++++++++++++------ 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/mythplugins/mythmusic/mythmusic/mythmusic.cpp b/mythplugins/mythmusic/mythmusic/mythmusic.cpp index 65a217aaa0e..3e77536de2d 100644 --- a/mythplugins/mythmusic/mythmusic/mythmusic.cpp +++ b/mythplugins/mythmusic/mythmusic/mythmusic.cpp @@ -481,7 +481,7 @@ static QStringList BuildFileList(const QString &dir, const QStringList &filters) return ret; } -static void handleMedia(MythMediaDevice *cd) +static void handleMedia(MythMediaDevice *cd, bool forcePlayback) { static QString s_mountPath; @@ -522,7 +522,7 @@ static void handleMedia(MythMediaDevice *cd) s_mountPath.clear(); // don't show the music screen if AutoPlayCD is off - if (!gCoreContext->GetBoolSetting("AutoPlayCD", false)) + if (!forcePlayback && !gCoreContext->GetBoolSetting("AutoPlayCD", false)) return; if (!gMusicData->m_initialized) @@ -627,7 +627,7 @@ static void handleMedia(MythMediaDevice *cd) } #ifdef HAVE_CDIO -static void handleCDMedia(MythMediaDevice *cd) +static void handleCDMedia(MythMediaDevice *cd, bool forcePlayback) { if (!cd) @@ -739,7 +739,7 @@ static void handleCDMedia(MythMediaDevice *cd) // if the AutoPlayCD setting is set we remove all the existing tracks // from the playlist and replace them with the new CD tracks found - if (gCoreContext->GetBoolSetting("AutoPlayCD", false)) + if (forcePlayback || gCoreContext->GetBoolSetting("AutoPlayCD", false)) { gMusicData->m_all_playlists->getActive()->removeAllTracks(); @@ -776,7 +776,7 @@ static void handleCDMedia(MythMediaDevice *cd) } } #else -static void handleCDMedia([[maybe_unused]] MythMediaDevice *cd) +static void handleCDMedia([[maybe_unused]] MythMediaDevice *cd, [[maybe_unused]] bool forcePlayback) { LOG(VB_GENERAL, LOG_NOTICE, "MythMusic got a media changed event" "but cdio support is not compiled in"); diff --git a/mythtv/libs/libmyth/mythmediamonitor.cpp b/mythtv/libs/libmyth/mythmediamonitor.cpp index a953de05b4d..0962337ca4f 100644 --- a/mythtv/libs/libmyth/mythmediamonitor.cpp +++ b/mythtv/libs/libmyth/mythmediamonitor.cpp @@ -635,14 +635,13 @@ QList MediaMonitor::GetMedias(unsigned mediatypes) * \param description Unused. * \param callback The function to call when an event occurs. * \param mediaType The type of media supported by this callback. The - * value must be an enum of type MythMediaType. + * value must be a bitmask of enums of type MythMediaType. * \param extensions A list of file name extensions supported by this * callback. */ void MediaMonitor::RegisterMediaHandler(const QString &destination, const QString &description, - void (*callback) - (MythMediaDevice*), + MediaCallback callback, int mediaType, const QString &extensions) { @@ -677,7 +676,7 @@ void MediaMonitor::RegisterMediaHandler(const QString &destination, * to allow the user to select which one to use, * but for now, we're going to just use the first one. */ -void MediaMonitor::JumpToMediaHandler(MythMediaDevice* pMedia) +void MediaMonitor::JumpToMediaHandler(MythMediaDevice* pMedia, bool forcePlayback) { QVector handlers; QMap::Iterator itr = m_handlerMap.begin(); @@ -705,7 +704,7 @@ void MediaMonitor::JumpToMediaHandler(MythMediaDevice* pMedia) // if user didn't cancel, selected = handlers.at(choice); int selected = 0; - handlers.at(selected).callback(pMedia); + handlers.at(selected).callback(pMedia, forcePlayback); } /** @@ -819,7 +818,7 @@ bool MediaMonitor::eventFilter(QObject *obj, QEvent *event) { if ((*itr).MythMediaType & (int)pDev->getMediaType() || pDev->getStatus() == MEDIASTAT_OPEN) - (*itr).callback(pDev); + (*itr).callback(pDev, false); itr++; } } diff --git a/mythtv/libs/libmyth/mythmediamonitor.h b/mythtv/libs/libmyth/mythmediamonitor.h index 18662f85ebc..ad282589d49 100644 --- a/mythtv/libs/libmyth/mythmediamonitor.h +++ b/mythtv/libs/libmyth/mythmediamonitor.h @@ -16,6 +16,8 @@ #include "libmythbase/mthread.h" #include "libmythbase/mythmedia.h" +typedef void (*MediaCallback)(MythMediaDevice *mediadevice, bool forcePlayback); + /// Stores details of media handlers // Adding member initializers caused compilation to fail with an error @@ -23,7 +25,7 @@ // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) struct MHData { - void (*callback)(MythMediaDevice *mediadevice); + MediaCallback callback; int MythMediaType; QString destination; QString description; @@ -78,10 +80,10 @@ class MPUBLIC MediaMonitor : public QObject void RegisterMediaHandler(const QString &destination, const QString &description, - void (*callback) (MythMediaDevice*), + MediaCallback callback, int mediaType, const QString &extensions); - void JumpToMediaHandler(MythMediaDevice* pMedia); + void JumpToMediaHandler(MythMediaDevice* pMedia, bool forcePlayback = false); // Plugins should use these if they need to access optical disks: static QString defaultCDdevice(); @@ -145,7 +147,7 @@ class MPUBLIC MediaMonitor : public QObject static inline void REG_MEDIA_HANDLER (const QString& destination, const QString& description, - void (*callback)(MythMediaDevice*), + MediaCallback callback, int mediaType, const QString& extensions) { diff --git a/mythtv/programs/mythfrontend/mythfrontend.cpp b/mythtv/programs/mythfrontend/mythfrontend.cpp index 3cb38f5aed1..30c79db9aa7 100644 --- a/mythtv/programs/mythfrontend/mythfrontend.cpp +++ b/mythtv/programs/mythfrontend/mythfrontend.cpp @@ -766,21 +766,12 @@ static void RunGallery() static void playDisc() { - // - // Get the command string to play a DVD - // - - bool isBD = false; - - QString command_string = - gCoreContext->GetSetting("mythdvd.DVDPlayerCommand"); + // Check for Bluray + LOG(VB_MEDIA, LOG_DEBUG, "Checking for BluRay medium"); QString bluray_mountpoint = gCoreContext->GetSetting("BluRayMountpoint", "/media/cdrom"); QDir bdtest(bluray_mountpoint + "/BDMV"); - - if (bdtest.exists() || MythCDROM::inspectImage(bluray_mountpoint) == MythCDROM::kBluray) - isBD = true; - + const bool isBD = (bdtest.exists() || MythCDROM::inspectImage(bluray_mountpoint) == MythCDROM::kBluray); if (isBD) { GetMythUI()->AddCurrentLocation("playdisc"); @@ -791,8 +782,19 @@ static void playDisc() 0, 0, "", 0min, "", "", true); GetMythUI()->RemoveCurrentLocation(); + return; } - else + + MediaMonitor *mediaMonitor = MediaMonitor::GetMediaMonitor(); + if (!mediaMonitor) + { + LOG(VB_MEDIA, LOG_ERR, "Could not access media monitor"); + return; + } + + // Check for DVD + LOG(VB_MEDIA, LOG_DEBUG, "Checking for DVD medium"); + if (!mediaMonitor->GetMedias(MEDIATYPE_DVD).isEmpty()) { QString dvd_device = MediaMonitor::defaultDVDdevice(); @@ -801,6 +803,9 @@ static void playDisc() GetMythUI()->AddCurrentLocation("playdisc"); + // Get the command string to play a DVD + QString command_string = + gCoreContext->GetSetting("mythdvd.DVDPlayerCommand"); if ((command_string.indexOf("internal", 0, Qt::CaseInsensitive) > -1) || (command_string.length() < 1)) { @@ -816,7 +821,7 @@ static void playDisc() command_string = "Internal"; GetMythMainWindow()->HandleMedia(command_string, filename, "", "", - "", "", 0, 0, "", 0min, "", "", true); + "", "", 0, 0, "", 0min, "", "", true); GetMythUI()->RemoveCurrentLocation(); return; @@ -840,13 +845,30 @@ static void playDisc() GetMythMainWindow()->activateWindow(); } GetMythUI()->RemoveCurrentLocation(); + return; } + + // Check for Audio CD + LOG(VB_MEDIA, LOG_DEBUG, "Checking for audio CD medium"); + auto audioMedia = mediaMonitor->GetMedias(MEDIATYPE_AUDIO | MEDIATYPE_MIXED); + if (!audioMedia.isEmpty()) + { + for (auto *medium : qAsConst(audioMedia)) + { + if (medium->isUsable()) { + LOG(VB_MEDIA, LOG_DEBUG, QString("Found usable audio/mixed device %1").arg(medium->getDevicePath())); + mediaMonitor->JumpToMediaHandler(medium, true); + return; + } + } + } + } ///////////////////////////////////////////////// //// Media handlers ///////////////////////////////////////////////// -static void handleDVDMedia(MythMediaDevice *dvd) +static void handleDVDMedia(MythMediaDevice *dvd, bool /*forcePlayback*/) { if (!dvd) return; @@ -868,7 +890,7 @@ static void handleDVDMedia(MythMediaDevice *dvd) } } -static void handleGalleryMedia(MythMediaDevice *dev) +static void handleGalleryMedia(MythMediaDevice *dev, bool forcePlayback) { // Only handle events for media that are newly mounted if (!dev || (dev->getStatus() != MEDIASTAT_MOUNTED @@ -890,7 +912,7 @@ static void handleGalleryMedia(MythMediaDevice *dev) } } - if (gCoreContext->GetBoolSetting("GalleryAutoLoad", false)) + if (forcePlayback || gCoreContext->GetBoolSetting("GalleryAutoLoad", false)) { LOG(VB_GUI, LOG_INFO, "Main: Autostarting Gallery for new media"); GetMythMainWindow()->JumpTo(JUMP_GALLERY_DEFAULT);