aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmake/treedata/freebsd/subdirs.txt1
-rw-r--r--cmake/treedata/linux/subdirs.txt1
-rw-r--r--cmake/treedata/osx/subdirs.txt1
-rw-r--r--xbmc/platform/posix/storage/discs/CMakeLists.txt7
-rw-r--r--xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.cpp153
-rw-r--r--xbmc/platform/posix/storage/discs/DiscDriveHandlerPosix.h58
-rw-r--r--xbmc/storage/DetectDVDType.cpp2
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))