Ticket #3379: cd-speed-patch

File cd-speed-patch, 11.1 KB (added by leoweppelman@…, 18 years ago)

cd-speed patch

Line 
1Index: libmythtv/DVDRingBuffer.cpp
2===================================================================
3--- libmythtv/DVDRingBuffer.cpp (revision 13250)
4+++ libmythtv/DVDRingBuffer.cpp (working copy)
5@@ -1,17 +1,8 @@
6 #include <unistd.h>
7-#ifdef __linux__
8-#include <linux/cdrom.h>
9-#include <scsi/sg.h>
10-#include <sys/types.h>
11-#include <sys/stat.h>
12-#include <sys/ioctl.h>
13-#include <fcntl.h>
14-#include <unistd.h>
15-#endif
16 
17-
18 #include "DVDRingBuffer.h"
19 #include "mythcontext.h"
20+#include "mythmediamonitor.h"
21 #include "iso639.h"
22 
23 #include "NuppelVideoPlayer.h"
24@@ -1150,109 +1141,22 @@
25     Seek(cellStart);
26 }
27 
28-/*
29- * \brief obtained from the mplayer project
30- */
31 void DVDRingBufferPriv::SetDVDSpeed(const char *device, int speed)
32 {
33-#if defined(__linux__) && defined(SG_IO) && defined(GPCMD_SET_STREAMING)
34-    int fd;
35-    unsigned char buffer[28];
36-    unsigned char cmd[16];
37-    unsigned char sense[16];
38-    struct sg_io_hdr sghdr;
39-    struct stat st;
40+    //
41+    // If it is OK to determine and lock the MythMediaDevice in
42+    // OpenFile() and unlock in CloseDVD(), this can be done
43+    // more efficiently.
44+    MediaMonitor *mon = MediaMonitor::GetMediaMonitor();
45 
46-    memset(&sghdr, 0, sizeof(sghdr));
47-    memset(buffer, 0, sizeof(buffer));
48-    memset(sense, 0, sizeof(sense));
49-    memset(cmd, 0, sizeof(cmd));
50-    memset(&st, 0, sizeof(st));
51-
52-    if (stat(device, &st) == -1 )
53-    {
54-        VERBOSE(VB_PLAYBACK, LOC_ERR +
55-                QString("SetDVDSpeed() Failed. device %1 not found")
56-                .arg(device));
57-        return;
58-    }
59-
60-    if (!S_ISBLK(st.st_mode))
61-    {
62-        VERBOSE(VB_PLAYBACK, LOC_ERR +
63-                "SetDVDSpeed() Failed. Not a block device");
64-        return;
65-    }
66-
67-    if ((fd = open(device, O_RDWR | O_NONBLOCK)) == -1)
68-    {
69-        VERBOSE(VB_PLAYBACK, LOC_ERR +
70-                "Changing DVD speed needs write access");
71-        return;
72-    }
73-
74-    if (speed > 0 && speed < 100)
75-        speed *= 1350;
76-
77-    switch(speed)
78-    {
79-        case 0: // don't touch speed setting
80-            return;
81-        case -1: // restore default value
82+    if (mon != NULL ) {
83+        MythMediaDevice *pMedia = mon->GetMedia(device);
84+        if (mon->ValidateAndLock(pMedia))
85         {
86-            speed = 0;
87-            buffer[0] = 4;
88-            VERBOSE(VB_PLAYBACK, LOC + "Restored DVD Speed");
89-            break;
90+            pMedia->setSpeed(speed);
91+            mon->Unlock(pMedia);
92         }
93-        default:
94-        {
95-            QString msg;
96-            if (speed < 0)
97-                msg = "Normal";
98-            else
99-                msg = QString("%1Kb/s").arg(speed);
100-            VERBOSE(VB_PLAYBACK, LOC + QString("Limit DVD Speed to %1")
101-                    .arg(msg));
102-            break;
103-        }
104     }
105-
106-    sghdr.interface_id = 'S';
107-    sghdr.timeout = 5000;
108-    sghdr.dxfer_direction = SG_DXFER_TO_DEV;
109-    sghdr.mx_sb_len = sizeof(sense);
110-    sghdr.dxfer_len = sizeof(buffer);
111-    sghdr.cmd_len = sizeof(cmd);
112-    sghdr.sbp = sense;
113-    sghdr.dxferp = buffer;
114-    sghdr.cmdp = cmd;
115-
116-    cmd[0] = GPCMD_SET_STREAMING;
117-    cmd[10] = sizeof(buffer);
118-
119-    buffer[8]  = 0xff;
120-    buffer[9]  = 0xff;
121-    buffer[10] = 0xff;
122-    buffer[11] = 0xff;
123-
124-    buffer[12] = buffer[20] = (speed >> 24) & 0xff;
125-    buffer[13] = buffer[21] = (speed >> 16) & 0xff;
126-    buffer[14] = buffer[22] = (speed >> 8)  & 0xff;
127-    buffer[15] = buffer[23] = speed & 0xff;
128-
129-    buffer[18] = buffer[26] = 0x03;
130-    buffer[19] = buffer[27] = 0xe8;
131-
132-    if (ioctl(fd, SG_IO, &sghdr) < 0)
133-        VERBOSE(VB_PLAYBACK, LOC_ERR + "Limit DVD Speed Failed");
134-   
135-    close(fd);
136-    VERBOSE(VB_PLAYBACK, LOC + "Limiting DVD Speed Successful");
137-#else
138-    (void)speed;
139-    (void)device;
140-#endif
141 }
142 
143 /**
144Index: libmyth/mythmediamonitor.h
145===================================================================
146--- libmyth/mythmediamonitor.h  (revision 13250)
147+++ libmyth/mythmediamonitor.h  (working copy)
148@@ -65,6 +65,7 @@
149     // first validate the pointer with ValidateAndLock(), if true is returned
150     // it is safe to dereference the pointer. When finished call Unlock()
151     QValueList<MythMediaDevice*> GetMedias(MediaType mediatype);
152+    MythMediaDevice* GetMedia(const QString &path);
153 
154     void MonitorRegisterExtensions(uint mediaType, const QString &extensions);
155 
156Index: libmyth/mythmedia.cpp
157===================================================================
158--- libmyth/mythmedia.cpp       (revision 13250)
159+++ libmyth/mythmedia.cpp       (working copy)
160@@ -273,6 +273,17 @@
161     return MEDIAERR_UNSUPPORTED;
162 }
163 
164+bool MythMediaDevice::isSameDevice(const QString &path)
165+{
166+    return (path == m_DevicePath);
167+}
168+
169+void MythMediaDevice::setSpeed(int speed)
170+{
171+    (void)speed;
172+    return;
173+}
174+
175 MediaError MythMediaDevice::lock()
176 {
177     // We just open the device here, which may or may not do the trick,
178Index: libmyth/mythmediamonitor.cpp
179===================================================================
180--- libmyth/mythmediamonitor.cpp        (revision 13250)
181+++ libmyth/mythmediamonitor.cpp        (working copy)
182@@ -379,6 +379,31 @@
183     }
184 }
185 
186+/**  \fn MediaMonitor::GetMedia(const QString& path)
187+ * \brief Get media device by pathname. Must be locked with ValidateAndLock().
188+ *
189+ *  \sa ValidateAndLock(MythMediaDevice *pMedia)
190+ *  \sa Unlock(MythMediaDevice *pMedia)
191+ */
192+MythMediaDevice* MediaMonitor::GetMedia(const QString& path)
193+{
194+    QMutexLocker locker(&m_DevicesLock);
195+
196+    QValueList<MythMediaDevice*>::iterator it = m_Devices.begin();
197+    for (;it != m_Devices.end(); it++)
198+    {
199+        if ((*it)->isSameDevice(path) &&
200+            (((*it)->getStatus() == MEDIASTAT_USEABLE) ||
201+             ((*it)->getStatus() == MEDIASTAT_MOUNTED) ||
202+             ((*it)->getStatus() == MEDIASTAT_NOTMOUNTED)))
203+        {
204+            return(*it);
205+        }
206+    }
207+
208+    return NULL;
209+}
210+
211 /** \fn MediaMonitor::GetMedias(MediaType mediatype)
212  *  \brief Ask for available media. Must be locked with ValidateAndLock().
213  *
214Index: libmyth/mythcdrom-linux.cpp
215===================================================================
216--- libmyth/mythcdrom-linux.cpp (revision 13250)
217+++ libmyth/mythcdrom-linux.cpp (working copy)
218@@ -2,11 +2,16 @@
219 #include "mythcdrom-linux.h"
220 #include <sys/ioctl.h>                // ioctls
221 #include <linux/cdrom.h>        // old ioctls for cdrom
222+#include <scsi/sg.h>
223+#include <fcntl.h>
224 #include <errno.h>
225 #include "mythcontext.h"
226 #include <linux/iso_fs.h>
227 #include <unistd.h>
228 
229+#define LOC QString("mythcdrom-linux: ")
230+#define LOC_ERR QString("mythcdrom-linux, Error: ")
231+
232 #define ASSUME_WANT_AUDIO 1
233 
234 class MythCDROMLinux: public MythCDROM
235@@ -22,6 +27,8 @@
236     virtual bool checkOK(void);
237     virtual MediaStatus checkMedia(void);
238     virtual MediaError eject(bool open_close = true);
239+    virtual void setSpeed(int speed);
240+    virtual bool isSameDevice(const QString &path);
241     virtual MediaError lock(void);
242     virtual MediaError unlock(void);
243 };
244@@ -309,3 +316,134 @@
245 
246     return MythMediaDevice::unlock();
247 }
248+
249+bool MythCDROMLinux::isSameDevice(const QString &path)
250+{
251+    dev_t new_rdev;
252+    struct stat sb;
253+
254+    if (stat(path, &sb) < 0)
255+    {
256+        VERBOSE(VB_IMPORTANT, "MythCDROMLinux::SameDevice() -- " +
257+                QString("Failed to stat '%1'")
258+                .arg(path) + ENO);
259+        return false;
260+    }
261+    new_rdev = sb.st_rdev;
262+
263+    // Check against m_DevicePath...
264+    if (stat(m_DevicePath, &sb) < 0)
265+    {
266+        VERBOSE(VB_IMPORTANT, "MythCDROMLinux::SameDevice() -- " +
267+                QString("Failed to stat '%1'")
268+                .arg(m_DevicePath) + ENO);
269+        return false;
270+    }
271+    return (sb.st_rdev == new_rdev);
272+}
273+
274+#if defined(SG_IO) && defined(GPCMD_SET_STREAMING)
275+/*
276+ * \brief obtained from the mplayer project
277+ */
278+void MythCDROMLinux::setSpeed(int speed)
279+{
280+    int fd;
281+    unsigned char buffer[28];
282+    unsigned char cmd[16];
283+    unsigned char sense[16];
284+    struct sg_io_hdr sghdr;
285+    struct stat st;
286+    int        rate = 0;
287+
288+    memset(&sghdr, 0, sizeof(sghdr));
289+    memset(buffer, 0, sizeof(buffer));
290+    memset(sense, 0, sizeof(sense));
291+    memset(cmd, 0, sizeof(cmd));
292+    memset(&st, 0, sizeof(st));
293+
294+    if (stat(m_DevicePath, &st) == -1 )
295+    {
296+        VERBOSE(VB_IMPORTANT, LOC_ERR +
297+                QString("setSpeed() Failed. device %1 not found")
298+                .arg(m_DevicePath));
299+        return;
300+    }
301+
302+    if (!S_ISBLK(st.st_mode))
303+    {
304+        VERBOSE(VB_IMPORTANT, LOC_ERR +
305+                "MythCDROMLinux::SetSpeed() Failed. Not a block device");
306+        return;
307+    }
308+
309+    if ((fd = open(m_DevicePath, O_RDWR | O_NONBLOCK)) == -1)
310+    {
311+        VERBOSE(VB_IMPORTANT, LOC_ERR +
312+                "Changing DVD speed needs write access");
313+        return;
314+    }
315+
316+    if (speed < 0)
317+        speed = -1;
318+
319+    switch(speed)
320+    {
321+        case 0: // don't touch speed setting
322+            return;
323+        case -1: // restore default value
324+        {
325+            rate = 0;
326+            buffer[0] = 4;
327+            VERBOSE(VB_IMPORTANT, LOC + "Restored DVD Speed");
328+            break;
329+        }
330+        default:
331+        {
332+            // Speed in Kilobyte/Second. 177KB/s is the maximum data rate
333+            // for standard Audio CD's.
334+
335+            rate = (speed > 0 && speed < 100) ? speed * 177 : speed;
336+
337+            VERBOSE(VB_IMPORTANT, LOC + QString("Limit DVD Speed to %1KB/s")
338+                    .arg(rate));
339+            break;
340+        }
341+    }
342+
343+    sghdr.interface_id = 'S';
344+    sghdr.timeout = 5000;
345+    sghdr.dxfer_direction = SG_DXFER_TO_DEV;
346+    sghdr.mx_sb_len = sizeof(sense);
347+    sghdr.dxfer_len = sizeof(buffer);
348+    sghdr.cmd_len = sizeof(cmd);
349+    sghdr.sbp = sense;
350+    sghdr.dxferp = buffer;
351+    sghdr.cmdp = cmd;
352+
353+    cmd[0] = GPCMD_SET_STREAMING;
354+    cmd[10] = sizeof(buffer);
355+
356+    buffer[8]  = 0xff;
357+    buffer[9]  = 0xff;
358+    buffer[10] = 0xff;
359+    buffer[11] = 0xff;
360+
361+    buffer[12] = buffer[20] = (rate >> 24) & 0xff;
362+    buffer[13] = buffer[21] = (rate >> 16) & 0xff;
363+    buffer[14] = buffer[22] = (rate >> 8)  & 0xff;
364+    buffer[15] = buffer[23] = rate & 0xff;
365+
366+    // Note: 0x3e8 == 1000, hence speed = data amount per 1000 milliseconds.
367+    buffer[18] = buffer[26] = 0x03;
368+    buffer[19] = buffer[27] = 0xe8;
369+
370+    // On my system (2.6.18 + ide-cd),  SG_IO succeeds without doing anything,
371+    // while CDROM_SELECT_SPEED works...
372+    if (ioctl(fd, CDROM_SELECT_SPEED, speed) < 0) {
373+        if (ioctl(fd, SG_IO, &sghdr) < 0)
374+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Limit DVD Speed Failed");
375+    }
376+    else VERBOSE(VB_IMPORTANT, LOC + "Limiting DVD Speed Successful");
377+}
378+#endif
379Index: libmyth/mythmedia.h
380===================================================================
381--- libmyth/mythmedia.h (revision 13250)
382+++ libmyth/mythmedia.h (working copy)
383@@ -81,6 +81,8 @@
384     virtual MediaError  testMedia() { return MEDIAERR_UNSUPPORTED; }
385     virtual bool openDevice();
386     virtual bool closeDevice();
387+    virtual bool isSameDevice(const QString &path);
388+    virtual void setSpeed(int speed);
389     virtual MediaStatus checkMedia() = 0; // Derived classes MUST implement this.
390     virtual MediaError eject(bool open_close = true);
391     virtual MediaError lock();