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 #define PATHTO_BAD_DVD_MOUNT "/video_ts"
33 
34 #define PATHTO_DVD_DETECT "/VIDEO_TS"
35 #define PATHTO_BD_DETECT "/BDMV"
36 #define PATHTO_VCD_DETECT "/vcd"
37 #define PATHTO_SVCD_DETECT "/svcd"
38 
39 // Mac OS X mounts audio CDs ready to use
40 #define 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, void *buf, uint32_t nblocks, int flags)
176 {
177  (void)flags;
178  int result = -1;
179  auto *p = (blockInput_t *)p_gen;
180 
181  if (p && p->m_file && (p->m_file->Seek(static_cast<long long>(lba) * UDF_BLOCK_SIZE, SEEK_SET) != -1))
182  result = p->m_file->Read(buf, nblocks * UDF_BLOCK_SIZE) / UDF_BLOCK_SIZE;
183 
184  return result;
185 }
186 
188 {
189  ImageType imageType = kUnknown;
190 
191  if (path.startsWith("bd:"))
192  imageType = kBluray;
193  else if (path.startsWith("dvd:"))
194  imageType = kDVD;
195  else
196  {
197  blockInput_t blockInput {};
198 
199  blockInput.m_file = new RemoteFile(path); // Normally deleted via a call to udfread_close
200  blockInput.m_input.close = def_close;
201  blockInput.m_input.read = def_read;
202  blockInput.m_input.size = def_size;
203 
204  if (blockInput.m_file->isOpen())
205  {
206  udfread *udf = udfread_init();
207  if (udfread_open_input(udf, &blockInput.m_input) == 0)
208  {
209  UDFDIR *dir = udfread_opendir(udf, "/BDMV");
210 
211  if (dir)
212  {
213  LOG(VB_MEDIA, LOG_INFO, QString("Found Bluray at %1").arg(path));
214  imageType = kBluray;
215  }
216  else
217  {
218  dir = udfread_opendir(udf, "/VIDEO_TS");
219 
220  if (dir)
221  {
222  LOG(VB_MEDIA, LOG_INFO, QString("Found DVD at %1").arg(path));
223  imageType = kDVD;
224  }
225  else
226  {
227  LOG(VB_MEDIA, LOG_ERR, QString("inspectImage - unknown"));
228  }
229  }
230 
231  if (dir)
232  {
233  udfread_closedir(dir);
234  }
235 
236  udfread_close(udf);
237  }
238  else
239  {
240  // Open failed, so we have clean this up here
241  delete blockInput.m_file;
242  }
243  }
244  else
245  {
246  LOG(VB_MEDIA, LOG_ERR, QString("inspectImage - unable to open \"%1\"").arg(path));
247  delete blockInput.m_file;
248  }
249  }
250 
251  return imageType;
252 }
MythCDROM::MythCDROM
MythCDROM(QObject *par, const QString &DevicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:57
PATHTO_VCD_DETECT
#define PATHTO_VCD_DETECT
Definition: mythcdrom.cpp:36
PATHTO_DVD_DETECT
#define PATHTO_DVD_DETECT
Definition: mythcdrom.cpp:34
MEDIATYPE_DVD
@ MEDIATYPE_DVD
Definition: mythmedia.h:29
MEDIATYPE_VCD
@ MEDIATYPE_VCD
Definition: mythmedia.h:30
MEDIATYPE_UNKNOWN
@ MEDIATYPE_UNKNOWN
Definition: mythmedia.h:25
MythCDROM::kUnknown
@ kUnknown
Definition: mythcdrom.h:28
blockInput_t::m_file
RemoteFile * m_file
Definition: mythcdrom.cpp:150
MythCDROM::kBluray
@ kBluray
Definition: mythcdrom.h:29
mythcdrom.h
MEDIASTAT_ERROR
@ MEDIASTAT_ERROR
Unable to mount, but could be usable.
Definition: mythmedia.h:13
MEDIASTAT_USEABLE
@ MEDIASTAT_USEABLE
Definition: mythmedia.h:19
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:23
MEDIASTAT_MOUNTED
@ MEDIASTAT_MOUNTED
Definition: mythmedia.h:21
def_read
static int def_read(udfread_block_input *p_gen, uint32_t lba, void *buf, uint32_t nblocks, int flags)
Definition: mythcdrom.cpp:175
mythcdrom-freebsd.h
MythCDROM::kDVD
@ kDVD
Definition: mythcdrom.h:30
mythlogging.h
PATHTO_SVCD_DETECT
#define PATHTO_SVCD_DETECT
Definition: mythcdrom.cpp:37
def_size
static uint32_t def_size(udfread_block_input *p_gen)
Definition: mythcdrom.cpp:168
remotefile.h
hardwareprofile.config.p
p
Definition: config.py:33
compat.h
MEDIATYPE_BD
@ MEDIATYPE_BD
Definition: mythmedia.h:34
GetMythCDROMLinux
MythCDROM * GetMythCDROMLinux(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom-linux.cpp:161
MythCDROM::ImageType
ImageType
Definition: mythcdrom.h:26
MythMediaDevice::unlock
virtual MythMediaError unlock()
Definition: mythmedia.cpp:350
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
MEDIATYPE_AUDIO
@ MEDIATYPE_AUDIO
Definition: mythmedia.h:28
MythMediaDevice::m_mountPath
QString m_mountPath
The path to this media's mount point.
Definition: mythmedia.h:153
PATHTO_BAD_DVD_MOUNT
#define PATHTO_BAD_DVD_MOUNT
Definition: mythcdrom.cpp:32
blockInput_t::m_input
udfread_block_input m_input
Definition: mythcdrom.cpp:149
PATHTO_AUDIO_DETECT
#define PATHTO_AUDIO_DETECT
Definition: mythcdrom.cpp:40
MythCDROM::inspectImage
static ImageType inspectImage(const QString &path)
Definition: mythcdrom.cpp:187
blockInput_t
Definition: mythcdrom.cpp:147
MythCDROM::get
static MythCDROM * get(QObject *par, const QString &devicePath, bool SuperMount, bool AllowEject)
Definition: mythcdrom.cpp:43
PATHTO_BD_DETECT
#define PATHTO_BD_DETECT
Definition: mythcdrom.cpp:35
mythcdrom-darwin.h
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
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
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
MEDIATYPE_DATA
@ MEDIATYPE_DATA
Definition: mythmedia.h:26