Hi! Here's a new version: - set cmd_len correctly (libata checks for correct cmd_len before passing commands through) - indent cleanup - earlier entry point to slow down drive before playback starts Todo: - proper error handling - try old SET CD/DVD SPEED command in case SET STREAMING isn't supported Regards Sebastian
diff -Nur dvd/i18n.c dvd.new/i18n.c --- dvd/i18n.c 2007-11-13 15:59:36.000000000 +0100 +++ dvd.new/i18n.c 2007-11-13 15:51:06.000000000 +0100 @@ -280,6 +280,32 @@ #endif }, { + "Setup.DVD$DVD-ROM Speed", // English + "DVD-ROM-Geschwindigkeit", // Deutsch + "DVD-ROM Speed", // Slovenski + "DVD-ROM Speed", // Italiano + "DVD-ROM Speed", // Nederlands + "DVD-ROM Speed", // Português + "DVD-ROM Speed", // Français + "DVD-ROM Speed", // Norsk + "DVD-ROM Speed", // suomi + "DVD-ROM Speed", // Polski + "DVD-ROM Speed", // Español + "DVD-ROM Speed", // ÅëëçíéêÜ (Greek) + "DVD-ROM Speed", // Svenska + "DVD-ROM Speed", // Romaneste + "DVD-ROM Speed", // Magyar + "DVD-ROM Speed", // Català + "DVD-ROM Speed", // ÀãááÚØÙ (Russian) + "DVD-ROM Speed", // Hrvatski (Croatian) + "DVD-ROM Speed", // Eesti + "DVD-ROM Speed", // Dansk + "DVD-ROM Speed", // Czech +#if VDRVERSNUM >= 10502 + "DVD-ROM Speed" // Türkçe +#endif + }, + { "Setup.DVD$Gain (analog)", "Verstärkung (analog)", // Deutsch "Ojaèanje (analogno)", // Slovenski diff -Nur dvd/player-dvd.c dvd.new/player-dvd.c --- dvd/player-dvd.c 2007-09-17 21:04:43.000000000 +0200 +++ dvd.new/player-dvd.c 2007-11-13 15:58:50.000000000 +0100 @@ -35,6 +35,11 @@ #include "control-dvd.h" #include "dvd.h" +/* Needed for DvdSetSpeed() */ +#include <linux/cdrom.h> +#include <scsi/sg.h> +#include <sys/ioctl.h> + /** * this was "weak"'s solution of a forced * SPU only stream choice, @@ -252,6 +257,7 @@ bool cDvdPlayer::HasBitStreamOut = false; bool cDvdPlayer::HasSoftDeviceOut = false; bool cDvdPlayer::SoftDeviceOutActive = false; +bool cDvdPlayer::DvdSetSpeedActive = false; const int cDvdPlayer::MaxAudioTracks = 0x20; const int cDvdPlayer::AudioTrackMask = 0x1F; @@ -565,6 +571,93 @@ #endif } +/* This function was ripped off of mplayer */ +void cDvdPlayer::DvdSetSpeed(const char *device, int speed) +{ +#if defined(SG_IO) && defined(GPCMD_SET_STREAMING) + int fd; + unsigned char buffer[28]; + unsigned char cmd[12]; + unsigned char sense[16]; + struct sg_io_hdr sghdr; + struct stat st; + + memset(&sghdr, 0, sizeof(sghdr)); + memset(buffer, 0, sizeof(buffer)); + memset(sense, 0, sizeof(sense)); + memset(cmd, 0, sizeof(cmd)); + memset(&st, 0, sizeof(st)); + + if (stat(device, &st) == -1) { + esyslog("ERROR: dvd-plugin: DVD device %s doesn't exist", device); + return; + } + + if (!S_ISBLK(st.st_mode)) { + esyslog("ERROR: dvd-plugin: DVD device %s is not a block device", device); + return; + } + + if ((fd = open(device, O_RDWR | O_NONBLOCK)) == -1) { + esyslog("ERROR: dvd-plugin: Failed to open DVD device %s O_RDWR | O_NONBLOCK", device); + return; + } + + if (speed < 100 && speed > 0) { /* speed times 1350KB/s (DVD single speed) */ + speed *= 1350; + } + + switch (speed) { + case 0: /* don't touch speed setting */ + close(fd); + return; + case -1: /* restore default value */ + speed = 0; + buffer[0] = 4; /* restore default */ + isyslog("dvd-plugin: Restoring initial DVD drive speed"); + break; + default: /* limit to <speed> KB/s */ + isyslog("dvd-plugin: Limiting speed to %d KB/s", speed); + break; + } + + sghdr.interface_id = 'S'; + sghdr.timeout = 5000; + sghdr.dxfer_direction = SG_DXFER_TO_DEV; + sghdr.mx_sb_len = sizeof(sense); + sghdr.dxfer_len = sizeof(buffer); + sghdr.cmd_len = sizeof(cmd); + sghdr.sbp = sense; + sghdr.dxferp = buffer; + sghdr.cmdp = cmd; + + cmd[0] = GPCMD_SET_STREAMING; + cmd[10] = sizeof(buffer); + + buffer[8] = 0xff; /* first sector 0, last sector 0xffffffff */ + buffer[9] = 0xff; + buffer[10] = 0xff; + buffer[11] = 0xff; + + buffer[12] = buffer[20] = (speed >> 24) & 0xff; /* <speed> kilobyte */ + buffer[13] = buffer[21] = (speed >> 16) & 0xff; + buffer[14] = buffer[22] = (speed >> 8) & 0xff; + buffer[15] = buffer[23] = speed & 0xff; + + buffer[18] = buffer[26] = 0x03; /* 1 second */ + buffer[19] = buffer[27] = 0xe8; + + if (ioctl(fd, SG_IO, &sghdr) < 0) { + esyslog("ERROR: dvd-plugin: DVD speed limiting failed"); + close(fd); + return; + } + isyslog("dvd-plugin: DVD speed limiting successful"); + DvdSetSpeedActive = true; + close(fd); +#endif +} + void cDvdPlayer::Action(void) { memset(event_buf, 0, sizeof(uint8_t)*4096); @@ -590,12 +683,21 @@ } dsyslog("dvd-plugin: SoftDeviceOutActive=%d, HasSoftDeviceOut=%d", SoftDeviceOutActive, HasSoftDeviceOut); + /* Try to reduce drive speed if the user wants us to */ + if (DVDSetup.Speed) + DvdSetSpeed(const_cast<char *>(cDVD::getDVD()->DeviceName()), DVDSetup.Speed); + if (dvdnav_open(&nav, const_cast<char *>(cDVD::getDVD()->DeviceName())) != DVDNAV_STATUS_OK) { Skins.Message(mtError, tr("Error.DVD$Error opening DVD!")); esyslog("ERROR: dvd-plugin cannot open dvdnav device %s -> input thread ended (pid=%d) !", const_cast<char *>(cDVD::getDVD()->DeviceName()), getpid()); active = running = false; nav=NULL; fflush(NULL); + /* Try to restore drive speed if it was previously changed */ + if (DvdSetSpeedActive) { + DvdSetSpeed(const_cast<char *>(cDVD::getDVD()->DeviceName()), -1); + DvdSetSpeedActive = false; + } return; } dvdnav_set_readahead_flag(nav, DVDSetup.ReadAHead); @@ -1203,6 +1305,12 @@ dvdnav_close(nav); nav=NULL; + /* Try to restore drive speed if it was previously changed */ + if (DvdSetSpeedActive) { + DvdSetSpeed(const_cast<char *>(cDVD::getDVD()->DeviceName()), -1); + DvdSetSpeedActive = false; + } + DEBUGDVD("%s:%d: input thread ended (pid=%d)\n", __FILE__, __LINE__, getpid()); fflush(NULL); } diff -Nur dvd/player-dvd.h dvd.new/player-dvd.h --- dvd/player-dvd.h 2007-09-17 21:04:43.000000000 +0200 +++ dvd.new/player-dvd.h 2007-11-13 15:51:06.000000000 +0100 @@ -168,6 +168,7 @@ static bool HasBitStreamOut; static bool SoftDeviceOutActive; // currently used to switch for xine static bool HasSoftDeviceOut; // currently used to switch for xine + static bool DvdSetSpeedActive; //dvd stuff int currButtonN; @@ -229,6 +230,7 @@ void DrawSPU(); void HideSPU(); void EmptySPU(); + void DvdSetSpeed(const char*, int); void Pause(void); void Play(void); diff -Nur dvd/setup-dvd.c dvd.new/setup-dvd.c --- dvd/setup-dvd.c 2007-11-13 15:59:36.000000000 +0100 +++ dvd.new/setup-dvd.c 2007-11-13 15:51:06.000000000 +0100 @@ -35,6 +35,7 @@ Gain = 4; AC3dynrng = 0; + Speed = 0; } bool cDVDSetup::SetupParse(const char *Name, const char *Value) @@ -47,6 +48,7 @@ else if (!strcasecmp(Name, "ShowSubtitles")) ShowSubtitles = atoi(Value); else if (!strcasecmp(Name, "HideMainMenu")) HideMainMenu = atoi(Value); else if (!strcasecmp(Name, "ReadAHead")) ReadAHead = atoi(Value); + else if (!strcasecmp(Name, "Speed")) Speed = atoi(Value); else if (!strcasecmp(Name, "Gain")) Gain = atoi(Value); else if (!strcasecmp(Name, "AC3dynrng")) AC3dynrng = atoi(Value); else @@ -73,6 +75,7 @@ Add(new cMenuEditBoolItem(tr("Setup.DVD$Display subtitles"), &data.ShowSubtitles)); Add(new cMenuEditBoolItem(tr("Setup.DVD$Hide Mainmenu Entry"), &data.HideMainMenu)); Add(new cMenuEditBoolItem(tr("Setup.DVD$ReadAHead"), &data.ReadAHead)); + Add(new cMenuEditIntItem( tr("Setup.DVD$DVD-ROM Speed"), &data.Speed, 0, 4)); Add(new cMenuEditIntItem( tr("Setup.DVD$Gain (analog)"), &data.Gain, 0, 10)); Add(new cMenuEditBoolItem(tr("Setup.DVD$A52 DRC"), &data.AC3dynrng)); } @@ -87,6 +90,7 @@ SetupStore("ShowSubtitles", DVDSetup.ShowSubtitles ); SetupStore("HideMainMenu", DVDSetup.HideMainMenu ); SetupStore("ReadAHead", DVDSetup.ReadAHead ); + SetupStore("Speed", DVDSetup.Speed ); SetupStore("Gain", DVDSetup.Gain ); SetupStore("AC3dynrng", DVDSetup.AC3dynrng ); } diff -Nur dvd/setup-dvd.h dvd.new/setup-dvd.h --- dvd/setup-dvd.h 2005-01-05 17:32:21.000000000 +0100 +++ dvd.new/setup-dvd.h 2007-11-13 15:51:06.000000000 +0100 @@ -23,6 +23,7 @@ int HideMainMenu; int ReadAHead; int Gain; + int Speed; // AC3 stuff int AC3dynrng;
_______________________________________________ vdr mailing list vdr@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr