diff options
-rw-r--r-- | cmake/treedata/freebsd/subdirs.txt | 1 | ||||
-rw-r--r-- | cmake/treedata/linux/subdirs.txt | 1 | ||||
-rw-r--r-- | cmake/treedata/osx/subdirs.txt | 1 | ||||
-rw-r--r-- | xbmc/platform/posix/storage/discs/CMakeLists.txt | 7 | ||||
-rw-r--r-- | xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.cpp | 153 | ||||
-rw-r--r-- | xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.h | 58 | ||||
-rw-r--r-- | xbmc/storage/DetectDVDType.cpp | 2 |
7 files changed, 222 insertions, 1 deletions
diff --git a/cmake/treedata/freebsd/subdirs.txt b/cmake/treedata/freebsd/subdirs.txt index ea5b3fac64..1e5515e9ab 100644 --- a/cmake/treedata/freebsd/subdirs.txt +++ b/cmake/treedata/freebsd/subdirs.txt @@ -10,6 +10,7 @@ xbmc/platform/linux/storage platform/linux/storage xbmc/platform/posix platform/posix xbmc/platform/posix/filesystem platform/posix/filesystem xbmc/platform/posix/network platform/posix/network +xbmc/platform/posix/storage/discs platform/posix/storage/discs xbmc/platform/posix/threads platform/posix/threads xbmc/platform/posix/utils platform/posix/utils xbmc/windowing/linux windowing/linux diff --git a/cmake/treedata/linux/subdirs.txt b/cmake/treedata/linux/subdirs.txt index 2325768962..440bea9afd 100644 --- a/cmake/treedata/linux/subdirs.txt +++ b/cmake/treedata/linux/subdirs.txt @@ -10,6 +10,7 @@ xbmc/platform/linux/storage platform/linux/storage xbmc/platform/posix platform/posix xbmc/platform/posix/filesystem platform/posix/filesystem xbmc/platform/posix/network platform/posix/network +xbmc/platform/posix/storage/discs platform/posix/storage/discs xbmc/platform/posix/threads platform/posix/threads xbmc/platform/posix/utils platform/posix/utils xbmc/windowing/linux windowing/linux diff --git a/cmake/treedata/osx/subdirs.txt b/cmake/treedata/osx/subdirs.txt index 92a948b81f..b9fc36e5cb 100644 --- a/cmake/treedata/osx/subdirs.txt +++ b/cmake/treedata/osx/subdirs.txt @@ -12,6 +12,7 @@ xbmc/platform/darwin/utils platform/darwin/utils xbmc/platform/posix posix xbmc/platform/posix/filesystem platform/posix/filesystem xbmc/platform/posix/network platform/posix/network +xbmc/platform/posix/storage/discs platform/posix/storage/discs xbmc/platform/posix/threads platform/posix/threads xbmc/platform/posix/utils platform/posix/utils xbmc/windowing/osx windowing/osx diff --git a/xbmc/platform/posix/storage/discs/CMakeLists.txt b/xbmc/platform/posix/storage/discs/CMakeLists.txt new file mode 100644 index 0000000000..7587043ef1 --- /dev/null +++ b/xbmc/platform/posix/storage/discs/CMakeLists.txt @@ -0,0 +1,7 @@ +if(ENABLE_OPTICAL) + set(SOURCES DiscDriveHandlerPosix.cpp) + + set(HEADERS DiscDriveHandlerPosix.h) + + core_add_library(platform_posix_storage_discs) +endif() diff --git a/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.cpp b/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.cpp new file mode 100644 index 0000000000..614955bd42 --- /dev/null +++ b/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2022 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "DiscDriveHandlerPosix.h" + +#include "storage/cdioSupport.h" +#include "utils/log.h" + +#include <memory> + +namespace +{ +constexpr int MAX_OPEN_RETRIES = 3; +} +using namespace MEDIA_DETECT; + +std::shared_ptr<IDiscDriveHandler> IDiscDriveHandler::CreateInstance() +{ + return std::make_shared<CDiscDriveHandlerPosix>(); +} + +DriveState CDiscDriveHandlerPosix::GetDriveState(const std::string& devicePath) +{ + DriveState driveStatus = DriveState::NOT_READY; + const std::shared_ptr<CLibcdio> libCdio = CLibcdio::GetInstance(); + if (!libCdio) + { + CLog::LogF(LOGERROR, "Failed to obtain libcdio handler"); + return driveStatus; + } + + CdIo_t* cdio = libCdio->cdio_open(devicePath.c_str(), DRIVER_UNKNOWN); + if (!cdio) + { + CLog::LogF(LOGERROR, "Failed to open device {} libcdio handler", devicePath); + return driveStatus; + } + + CdioTrayStatus status = libCdio->mmc_get_tray_status(cdio); + + switch (status) + { + case CdioTrayStatus::CLOSED: + driveStatus = DriveState::CLOSED_MEDIA_UNDEFINED; + break; + + case CdioTrayStatus::OPEN: + driveStatus = DriveState::OPEN; + break; + + case CdioTrayStatus::DRIVER_ERROR: + driveStatus = DriveState::NOT_READY; + break; + + default: + CLog::LogF(LOGWARNING, "Unknown/unhandled drive state interpreted as DRIVE_NOT_READY"); + break; + } + libCdio->cdio_destroy(cdio); + + return driveStatus; +} + +TrayState CDiscDriveHandlerPosix::GetTrayState(const std::string& devicePath) +{ + TrayState trayStatus = TrayState::UNDEFINED; + const std::shared_ptr<CLibcdio> libCdio = CLibcdio::GetInstance(); + if (!libCdio) + { + CLog::LogF(LOGERROR, "Failed to obtain libcdio handler"); + return trayStatus; + } + + discmode_t discmode = CDIO_DISC_MODE_NO_INFO; + CdIo_t* cdio = libCdio->cdio_open(devicePath.c_str(), DRIVER_UNKNOWN); + if (!cdio) + { + CLog::LogF(LOGERROR, "Failed to open device {} libcdio handler", devicePath); + return trayStatus; + } + + discmode = libCdio->cdio_get_discmode(cdio); + + if (discmode == CDIO_DISC_MODE_NO_INFO) + { + trayStatus = TrayState::CLOSED_NO_MEDIA; + } + else if (discmode == CDIO_DISC_MODE_ERROR) + { + trayStatus = TrayState::UNDEFINED; + } + else + { + trayStatus = TrayState::CLOSED_MEDIA_PRESENT; + } + libCdio->cdio_destroy(cdio); + + return trayStatus; +} + +void CDiscDriveHandlerPosix::EjectDriveTray(const std::string& devicePath) +{ + const std::shared_ptr<CLibcdio> libCdio = CLibcdio::GetInstance(); + if (!libCdio) + { + CLog::LogF(LOGERROR, "Failed to obtain libcdio handler"); + return; + } + + int retries = MAX_OPEN_RETRIES; + CdIo_t* cdio = libCdio->cdio_open(devicePath.c_str(), DRIVER_UNKNOWN); + while (cdio && retries-- > 0) + { + const driver_return_code_t ret = libCdio->cdio_eject_media(&cdio); + libCdio->cdio_destroy(cdio); + if (ret == DRIVER_OP_SUCCESS) + break; + } +} + +void CDiscDriveHandlerPosix::CloseDriveTray(const std::string& devicePath) +{ + const std::shared_ptr<CLibcdio> libCdio = CLibcdio::GetInstance(); + if (!libCdio) + { + CLog::LogF(LOGERROR, "Failed to obtain libcdio handler"); + return; + } + + const driver_return_code_t ret = libCdio->cdio_close_tray(devicePath.c_str(), nullptr); + if (ret != DRIVER_OP_SUCCESS) + { + CLog::LogF(LOGERROR, "Closing tray failed for device {}: {}", devicePath, + libCdio->cdio_driver_errmsg(ret)); + } +} + +void CDiscDriveHandlerPosix::ToggleDriveTray(const std::string& devicePath) +{ + if (GetDriveState(devicePath) == DriveState::OPEN) + { + CloseDriveTray(devicePath); + } + else + { + EjectDriveTray(devicePath); + } +} diff --git a/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.h b/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.h new file mode 100644 index 0000000000..11c4d9afab --- /dev/null +++ b/xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2022 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "storage/discs/IDiscDriveHandler.h" + +#include <string> + +class CDiscDriveHandlerPosix : public IDiscDriveHandler +{ +public: + /*! \brief Posix DiscDriveHandler constructor + */ + CDiscDriveHandlerPosix() = default; + + /*! \brief Posix DiscDriveHandler default destructor + */ + ~CDiscDriveHandlerPosix() override = default; + + /*! \brief Get the optical drive state provided its device path + * \param devicePath the path for the device drive (e.g. /dev/sr0) + * \return The drive state + */ + DriveState GetDriveState(const std::string& devicePath) override; + + /*! \brief Get the optical drive tray state provided the drive device path + * \param devicePath the path for the device drive (e.g. /dev/sr0) + * \return The drive state + */ + TrayState GetTrayState(const std::string& devicePath) override; + + /*! \brief Eject the provided drive device + * \param devicePath the path for the device drive (e.g. /dev/sr0) + */ + void EjectDriveTray(const std::string& devicePath) override; + + /*! \brief Close the provided drive device + * \note Some drives support closing appart from opening/eject + * \param devicePath the path for the device drive (e.g. /dev/sr0) + */ + void CloseDriveTray(const std::string& devicePath) override; + + /*! \brief Toggle the state of a given drive device + * + * Will internally call EjectDriveTray or CloseDriveTray depending on + * the internal state of the drive (i.e. if open -> CloseDriveTray / + * if closed -> EjectDriveTray) + * + * \param devicePath the path for the device drive (e.g. /dev/sr0) + */ + void ToggleDriveTray(const std::string& devicePath) override; +}; diff --git a/xbmc/storage/DetectDVDType.cpp b/xbmc/storage/DetectDVDType.cpp index 4c2c15601a..a5302de40a 100644 --- a/xbmc/storage/DetectDVDType.cpp +++ b/xbmc/storage/DetectDVDType.cpp @@ -321,7 +321,7 @@ DWORD CDetectDVDMedia::GetTrayState() if (cdio) { static discmode_t discmode = CDIO_DISC_MODE_NO_INFO; - int status = m_cdio->mmc_get_tray_status(cdio); + int status = static_cast<int>(m_cdio->mmc_get_tray_status(cdio)); static int laststatus = -1; // We only poll for new discmode when status has changed or there have been read errors (The last usually happens when new media is inserted) if (status == 0 && (laststatus != status || discmode == CDIO_DISC_MODE_ERROR)) |