MythTV  master
mythcdrom.cpp
Go to the documentation of this file.
1 #include "mythcdrom.h"
2 
3 #ifdef HAVE_LIBUDFREAD
4 #include <udfread/udfread.h>
5 #include <udfread/blockinput.h>
6 #else
7 #include "udfread.h"
8 #include "blockinput.h"
9 #endif
10 
11 #include <QtGlobal>
12 #include <QDir>
13 #include <QFileInfo>
14 
15 #include "compat.h"
16 #include "mythconfig.h"
17 #include "mythlogging.h"
18 #include "remotefile.h"
19 
20 #ifdef __linux__
21 # include "mythcdrom-linux.h"
22 #elif defined(__FreeBSD__)
23 # include "mythcdrom-freebsd.h"
24 #elif defined(Q_OS_DARWIN)
25 # include "mythcdrom-darwin.h"
26 #endif
27 
28 // If your DVD has directories in lowercase, then it is wrongly mounted!
29 // DVDs use the UDF filesystem, NOT ISO9660. Fix your /etc/fstab.
30 
31 // This allows a warning for the above mentioned OS setup fault
32 static constexpr const char* PATHTO_BAD_DVD_MOUNT { "/video_ts" };
33 
34 static constexpr const char* PATHTO_DVD_DETECT { "/VIDEO_TS" };
35 static constexpr const char* PATHTO_BD_DETECT { "/BDMV" };
36 static constexpr const char* PATHTO_VCD_DETECT { "/vcd" };
37 static constexpr const char* PATHTO_SVCD_DETECT { "/svcd" };
38 
39 // Mac OS X mounts audio CDs ready to use
40 static constexpr const char* PATHTO_AUDIO_DETECT { "/.TOC.plist" };
41 
42 
43 MythCDROM* MythCDROM::get(QObject* par, const QString& devicePath,
44  bool SuperMount, bool AllowEject)
45 {
46 #if defined(__linux__) && !defined(Q_OS_ANDROID)
47  return GetMythCDROMLinux(par, devicePath, SuperMount, AllowEject);
48 #elif defined(__FreeBSD__)
49  return GetMythCDROMFreeBSD(par, devicePath, SuperMount, AllowEject);
50 #elif defined(Q_OS_DARWIN)
51  return GetMythCDROMDarwin(par, devicePath, SuperMount, AllowEject);
52 #else
53  return new MythCDROM(par, devicePath, SuperMount, AllowEject);
54 #endif
55 }
56 
57 MythCDROM::MythCDROM(QObject* par, const QString& DevicePath, bool SuperMount,
58  bool AllowEject)
59  : MythMediaDevice(par, DevicePath, SuperMount, AllowEject)
60 {
61 }
62 
64 {
65  if (!QDir(m_mountPath).exists())
66  {
67  LOG(VB_GENERAL, LOG_ERR, QString("Mountpoint '%1' doesn't exist")
68  .arg(m_mountPath));
71  return;
72  }
73 
74  QFileInfo audio = QFileInfo(m_mountPath + PATHTO_AUDIO_DETECT);
75  QDir dvd = QDir(m_mountPath + PATHTO_DVD_DETECT);
76  QDir svcd = QDir(m_mountPath + PATHTO_SVCD_DETECT);
77  QDir vcd = QDir(m_mountPath + PATHTO_VCD_DETECT);
78  QDir bad_dvd = QDir(m_mountPath + PATHTO_BAD_DVD_MOUNT);
79  QDir bd = QDir(m_mountPath + PATHTO_BD_DETECT);
80 
81  // Default is data media
83 
84  // Default is mounted media
86 
87  if (dvd.exists())
88  {
89  LOG(VB_MEDIA, LOG_INFO, "Probable DVD detected.");
92  }
93  else if (bd.exists())
94  {
95  LOG(VB_MEDIA, LOG_INFO, "Probable Blu-ray detected.");
98  }
99  else if (audio.exists())
100  {
101  LOG(VB_MEDIA, LOG_INFO, "Probable Audio CD detected.");
104  }
105  else if (vcd.exists() || svcd.exists())
106  {
107  LOG(VB_MEDIA, LOG_INFO, "Probable VCD/SVCD detected.");
110  }
111  else if (bad_dvd.exists())
112  {
113  LOG(VB_GENERAL, LOG_ERR,
114  "DVD incorrectly mounted? (ISO9660 instead of UDF)");
115  }
116  else
117  {
118  LOG(VB_GENERAL, LOG_ERR,
119  QString("CD/DVD '%1' contained none of\n").arg(m_mountPath) +
120  QString("\t\t\t%1, %2, %3 or %4")
123  LOG(VB_GENERAL, LOG_INFO, "Searching CD statistically - file by file!");
124  }
125 
126  // If not DVD/AudioCD/VCD/SVCD, use parent's more generic version
129 
130  // Unlock the door, and if appropriate unmount the media,
131  // so the user can press the manual eject button
132  if (m_allowEject)
133  {
134  unlock();
136  unmount();
137  }
138 }
139 
140 void MythCDROM::setDeviceSpeed(const char *devicePath, int speed)
141 {
142  LOG(VB_MEDIA, LOG_INFO,
143  QString("SetDeviceSpeed(%1,%2) - not implemented on this OS.")
144  .arg(devicePath).arg(speed));
145 }
146 
148 {
149  udfread_block_input m_input; /* This *must* be the first entry in the struct */
151 };
152 
153 static int def_close(udfread_block_input *p_gen)
154 {
155  auto *p = (blockInput_t *)p_gen;
156  int result = -1;
157 
158  if (p && p->m_file)
159  {
160  delete p->m_file;
161  p->m_file = nullptr;
162  result = 0;
163  }
164 
165  return result;
166 }
167 
168 static uint32_t def_size(udfread_block_input *p_gen)
169 {
170  auto *p = (blockInput_t *)p_gen;
171 
172  return (uint32_t)(p->m_file->GetRealFileSize() / UDF_BLOCK_SIZE);
173 }
174 
175 static int def_read(udfread_block_input *p_gen, uint32_t lba,
176  void *buf, uint32_t nblocks,
177  [[maybe_unused]] int flags)
178 {
179  int result = -1;
180  auto *p = (blockInput_t *)p_gen;
181 
182  if (p && p->m_file && (p->m_file->Seek(static_cast<long long>(lba) * UDF_BLOCK_SIZE, SEEK_SET) != -1))
183  result = p->m_file->Read(buf, nblocks * UDF_BLOCK_SIZE) / UDF_BLOCK_SIZE;
184 
185  return result;
186 }
187 
189 {
190  ImageType imageType = kUnknown;
191 
192  if (path.startsWith("bd:"))
193  imageType = kBluray;
194  else if (path.startsWith("dvd:"))
195  imageType = kDVD;
196  else
197  {
198  blockInput_t blockInput {};
199 
200  blockInput.m_file = new RemoteFile(path); // Normally deleted via a call to udfread_close
201  blockInput.m_input.close = def_close;
202  blockInput.m_input.read = def_read;
203  blockInput.m_input.size = def_size;
204 
205  if (blockInput.m_file->isOpen())
206  {
207  udfread *udf = udfread_init();
208  if (udfread_open_input(udf, &blockInput.m_input) == 0)
209  {
210  UDFDIR *dir = udfread_opendir(udf, "/BDMV");
211 
212  if (dir)
213  {
214  LOG(VB_MEDIA, LOG_INFO, QString("Found Bluray at %1").arg(path));
215  imageType = kBluray;
216  }
217  else
218  {
219  dir = udfread_opendir(udf, "/VIDEO_TS");
220 
221  if (dir)
222  {
223  LOG(VB_MEDIA, LOG_INFO, QString("Found DVD at %1").arg(path));
224  imageType = kDVD;
225  }
226  else
227  {
228  LOG(VB_MEDIA, LOG_ERR, QString("inspectImage - unknown"));
229  }
230  }
231 
232  if (dir)
233  {
234  udfread_closedir(dir);
235  }
236 
237  udfread_close(udf);
238  }
239  else
240  {
241  // Open failed, so we have clean this up here
242  delete blockInput.m_file;
243  }
244  }
245  else
246  {
247  LOG(VB_MEDIA, LOG_ERR, QString("inspectImage - unable to open \"%1\"").arg(path));
248  delete blockInput.m_file;
249  }
250  }
251 
252  return imageType;
253 }
MEDIASTAT_ERROR
@ MEDIASTAT_ERROR
Unable to mount, but could be usable.
Definition: mythmedia.h:13
MythCDROM::MythCDROM
MythCDROM(QObject *par, const QString &DevicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:57
MEDIATYPE_DVD
@ MEDIATYPE_DVD
Definition: mythmedia.h:29
MEDIATYPE_UNKNOWN
@ MEDIATYPE_UNKNOWN
Definition: mythmedia.h:25
blockInput_t::m_file
RemoteFile * m_file
Definition: mythcdrom.cpp:150
mythcdrom.h
MEDIASTAT_USEABLE
@ MEDIASTAT_USEABLE
Definition: mythmedia.h:19
xbmcvfs.exists
bool exists(str path)
Definition: xbmcvfs.py:51
RemoteFile
Definition: remotefile.h:17
GetMythCDROMFreeBSD
MythCDROM * GetMythCDROMFreeBSD(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom-freebsd.cpp:26
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
mythcdrom-freebsd.h
PATHTO_VCD_DETECT
static constexpr const char * PATHTO_VCD_DETECT
Definition: mythcdrom.cpp:36
mythlogging.h
def_size
static uint32_t def_size(udfread_block_input *p_gen)
Definition: mythcdrom.cpp:168
remotefile.h
MythCDROM::kBluray
@ kBluray
Definition: mythcdrom.h:29
hardwareprofile.config.p
p
Definition: config.py:33
compat.h
GetMythCDROMLinux
MythCDROM * GetMythCDROMLinux(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom-linux.cpp:161
MythMediaDevice::unlock
virtual MythMediaError unlock()
Definition: mythmedia.cpp:352
MythMediaDevice::unmount
bool unmount()
Definition: mythmedia.h:108
MythCDROM
Definition: mythcdrom.h:6
MythMediaDevice::onDeviceMounted
virtual void onDeviceMounted(void)
Override this to perform any post mount logic.
Definition: mythmedia.h:133
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
MythMediaDevice::m_mountPath
QString m_mountPath
The path to this media's mount point.
Definition: mythmedia.h:153
def_read
static int def_read(udfread_block_input *p_gen, uint32_t lba, void *buf, uint32_t nblocks, [[maybe_unused]] int flags)
Definition: mythcdrom.cpp:175
MEDIATYPE_VCD
@ MEDIATYPE_VCD
Definition: mythmedia.h:30
MythCDROM::kUnknown
@ kUnknown
Definition: mythcdrom.h:28
blockInput_t::m_input
udfread_block_input m_input
Definition: mythcdrom.cpp:149
PATHTO_BAD_DVD_MOUNT
static constexpr const char * PATHTO_BAD_DVD_MOUNT
Definition: mythcdrom.cpp:32
PATHTO_SVCD_DETECT
static constexpr const char * PATHTO_SVCD_DETECT
Definition: mythcdrom.cpp:37
MythCDROM::inspectImage
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:188
blockInput_t
Definition: mythcdrom.cpp:147
MEDIATYPE_AUDIO
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
MythCDROM::get
static MythCDROM * get(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:43
mythcdrom-darwin.h
PATHTO_BD_DETECT
static constexpr const char * PATHTO_BD_DETECT
Definition: mythcdrom.cpp:35
MythCDROM::ImageType
ImageType
Definition: mythcdrom.h:26
PATHTO_AUDIO_DETECT
static constexpr const char * PATHTO_AUDIO_DETECT
Definition: mythcdrom.cpp:40
MythCDROM::kDVD
@ kDVD
Definition: mythcdrom.h:30
MEDIATYPE_BD
@ MEDIATYPE_BD
Definition: mythmedia.h:34
MythMediaDevice::m_allowEject
bool m_allowEject
Allow the user to eject the media?. Read only.
Definition: mythmedia.h:165
mythcdrom-linux.h
MythCDROM::onDeviceMounted
void onDeviceMounted() override
Override this to perform any post mount logic.
Definition: mythcdrom.cpp:63
MythCDROM::setDeviceSpeed
void setDeviceSpeed(const char *devicePath, int speed) override
Definition: mythcdrom.cpp:140
MEDIATYPE_DATA
@ MEDIATYPE_DATA
Definition: mythmedia.h:26
MythMediaDevice
Definition: mythmedia.h:48
MythMediaDevice::m_status
MythMediaStatus m_status
The status of the media as of the last call to checkMedia.
Definition: mythmedia.h:159
PATHTO_DVD_DETECT
static constexpr const char * PATHTO_DVD_DETECT
Definition: mythcdrom.cpp:34
def_close
static int def_close(udfread_block_input *p_gen)
Definition: mythcdrom.cpp:153
MythMediaDevice::m_mediaType
MythMediaType m_mediaType
The type of media. Read only.
Definition: mythmedia.h:162
GetMythCDROMDarwin
MythCDROM * GetMythCDROMDarwin(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom-darwin.cpp:24