Sony XL1B2
From MythTV
Overview
The Sony XL1B2 is a Firewire 200-DVD changer with a double-layer burner which is usable in both Linux and MythTV.
It is possible to use this unit with Linux and MythTv, several patches have been developed or are under development to fully support this unit. I encourage anyone who is interested to ask about this device on the appropriate mailing list(s) and to add any relevant feature requests so that this device and perhaps other similar ones can be supported properly.
To get this device working you will need to ensure that ieee1394, sbp2, scsi changer and scsi cd rom/dvd support are enabled in your Kernel. If all is well then the unit will appear as 2 scsi devices 1 changer device and 1 scsi cdrom /dvd device e.g. /dev/sg2 and /dev/sr0. It is also possible to create a udev rule to give the changer a suitable symlink, the changer is a type8 sg device. Although I have experienced issues with mtx locking up when this is created after bootup.
The mtx command is used to control the changer, MythTv and other application can use this command to change discs. You will currently need a patch for mtx in order for it to work correctly with the Sony VAIO media changer, you can ask for this on the mtx mailing list at http://sourceforge.net/mail/?group_id=4626. This patch also adds some feedback to stdout in order to help integration with other applications. When working correctly the device will show something like the following
# mtx -f /dev/sg2 altquerymode status
Storage Changer /dev/sg2:1 Drives, 201 Slots ( 1 Import/Export ) Data Transfer Element 0:Empty
Storage Element 1 IMPORT/EXPORT:Empty
Storage Element 2:Full
Storage Element 3:Empty
......
Storage Element 200:Empty
Storage Element 201:Empty
Support for the changer is now available in the latest mtx although it uses a slightly different syntax than above.
Support for batch CD ripping, changer inventory and playback of loaded DVDs in MythVideo have been added to my local copy of myth, although this support is very preliminary it has been tested and does work correctly. The jobs are currently offloaded to mtd and run in the background. It should also be possible to support multiple changers or changers other than the Sony utilising these patches. Please ask on the appropriate Myth mailing lists if any details are required I will do my best to help (alternately you can try nodenet at hotmail dot com, although you may be filtered as spam :) ). It will also be possible to add support for MythArchive and batch DVD ripping in a similar manner.
It's worth noting that currently when batch ripping CDs if a faulty disc is encountered, the device may become disabled and unresponsive. A patch for this has been submitted (to sbp2) that allows the device to recover and has removed the need for a reboot when this problem occurs, it is of course still possible that the ripping process may try and read a faulty disc indefinitely if there is a problem. You can ask for this patch at https://lists.sourceforge.net/lists/listinfo/linux1394-devel
It may also be useful to use the regionset utility to set the region code of the changer drive if you are not in region 1 (current default).
Scripts
It is possible as an alternative to modifying mythtv to use scripts to load / unload the changer. A suitable approach may be something like the following
- Create a stub file with a unique file extension for each dvd changer slot
- You could use mtx output to create them for only the loaded slots
- The stub file needs to convey the appropriate information to load / unload the correct slot
- Configure mythtv to recognise the file extension as a video file and write an appropriate wrapper script to load / play the dvd
- You will need to put the stub files in your video directory and scan them in with mythvideo so they appear in your video list
This approach should have the advantage of working with a standard mythtv release. You should still be able to enter meta data against your stub files. The scripts below should help with this, I don't have an inventory script unfortunately as the inventory I use was created with the original patched version of mtd using mysql tables. However as the approach is similar I feel the above should still work.
The scripts below were created using the patched mtx, the syntax will be different now. They are currently used with ssh to allow the front end to load / unload the desired disc.
mythdvdchangerload.sh
#!/bin/bash
#chng=`dmesg | grep -e 'ch .*sg[0-9] type 8' | tail -1 | sed -e 's/.*\(sg[0-9]\).*/\/dev\/\1/'`
#the above can be used to find most recent device no of changer
#udev rules now creates ch0 for type8 sg device
#chng=/dev/ch0
#symlink only works if changer connected b4 power on of server otherwise causes mtx to lock up
chng=`ls -l /dev/ch0 | sed -e 's/.*\(sg[0-9]\).*/\/dev\/\1/'`
if /usr/local/sbin/mtx -f $chng altquerymode drivestatus | grep -q "Slot: Empty"
then
echo "Good!...Changer drive is empty"
else
echo "Changer is still loaded.... attempting to unload drive"
if /usr/bin/eject -v /dev/sr0 | grep -q "eject command succeeded"
then
echo "Eject command succeeded (drive spindown)"
else
exit 0
fi
/usr/local/sbin/mtx -f $chng altquerymode unload
if /usr/local/sbin/mtx -f $chng altquerymode drivestatus | grep -q "Slot: Empty"
then
echo "Good!...Changer drive is now empty"
else
echo "Error: Changer is still loaded...aborting"
exit 0
fi
fi
if /usr/local/sbin/mtx -f $chng altquerymode load $1 | grep -q "Status: OK"
then
echo "Slot $1 load succeeded...waiting 5 seconds for disc to settle"
sleep 5
else
exit 0
fi
exit 1
mythdvdchangerunload.sh
#!/bin/bash
# chng=`dmesg | grep -e 'ch .*sg[0-9] type 8' | tail -1 | sed -e 's/.*\(sg[0-9]\).*/\/dev\/\1/'`
#the above can be used to find most recent device no of changer
#udev rules now creates ch0 for type8 sg device
#chng=/dev/ch0
#symlink only works if changer connected b4 power on of server otherwise causes mtx to lock up
chng=`ls -l /dev/ch0 | sed -e 's/.*\(sg[0-9]\).*/\/dev\/\1/'`
if /usr/local/sbin/mtx -f $chng altquerymode drivestatus | grep -q "Slot: Empty"
then
echo "Good!...Changer drive is empty"
else
echo "Changer is still loaded.... attempting to unload drive"
if /usr/bin/eject -v /dev/sr0 | grep -q "eject command succeeded"
then
echo "Eject command succeeded (drive spindown)"
else
exit 0
fi
/usr/local/sbin/mtx -f $chng altquerymode unload
if /usr/local/sbin/mtx -f $chng altquerymode drivestatus | grep -q "Slot: Empty"
then
echo "Good!...Changer drive is now empty"
else
echo "Error: Changer is still loaded...aborting"
exit 0
fi
fi
exit 1
This is an example of a script that can be run from the front end to play a dvd using the changer. It is designed to work with a remote dvd changer. To make it work you would need to configure ssh to login without a password for the appropriate user. Xine would also need to be patched with the cdda_server patch and the cdda_server would of course need to be running on the remote machine. The xine -r syntax may be something which I added and may not be supported normally (I forget). I've found the cdda_server patch to be a bit chopy for dvd playback but perhaps other people will have more luck.
If the dvd changer is connected directly to your front end there is of course no need to use ssh and xine can be told to use your local dvd changer drive e.g. /dev/sr0 (hence no need for the cdda_server patch either).
As my mythtv installation already had mysql tables I do not use stub files myself and have patched my current mythtv installation to provide the slot number as $1. If you wanted to run this without patching mythvideo you would need to get the correct slot number from the stub file name or stub file contents.
mythplaydvdchangerslot.sh
ssh <user@dvdserver> /usr/local/bin/mythdvdchangerload.sh $1 xine -pq --no-splash -r anamorphic dvd://<dvdserver>:3000/ ssh <user@dvdserver> /usr/local/bin/mythdvdchangerunload.sh &
Assuming your changer is physically attached to your frontend machine, this perl script will take inventory of the changer and write stub files that you can use to import into MythVideo and change to the correct disc as easy as choosing a video from the menu.
A couple of things to note:
- lsdvd is required to read the label from the disc to make meaningful stub files
- The script assumes you have the above scripts working and installed in a location in your $PATH and are executable (I had to modify the scripts above. If you can't get them working, please post to the mythv-users list for help.)
- The script assumes you'll be using mplayer to play back the video files. Modify if you like.
- osd_cat is very helpful. If installed, the stub files will make a call to osd_cat to alert the user that the disc is loading. It takes a long time, so a "please wait" message is helpful. You need to manually add a text file called "loading.txt" in the same location as your stub files containing the text that you want displayed in order for this to work. Also, I have chosen to display with the Vera Sans Mono font. Modify to your liking.
- -startfrom tells the script to ignore any full slots before this number. Suppose you put 30 DVDs in the changer, run the script and then load 30 more, you would use -startfrom 31 to ignore the 30 you already have stub files for. This script will always ignore empty slots. There is no "endon" number so it will always inventory until there are no more full slots. If you fill a slot between slots you've already inventoried, you're on your own.
- -device, -changer, -location are all set to what I use. Obviously, you need to know this information before you run the script
- Script will append slot number to stub file name if to avoid overwriting files that already exist (Helpful for generic DVD labels like DVD_VOLUME)
- The script takes a very long time to run. It essentially unloads the changer, gets the status to see which slots are full, loads each disc is finds (first issuing an unload command in case a disc is still loaded), reads the label from the disc, writes a stub file and moves on to the next one.
mythdvdchangerinventory.pl
#!/usr/bin/perl -w
use strict;
use Getopt::Long;
use vars qw( $opt_startfrom $opt_device $opt_changer $opt_location $opt_help );
my @optl = ( "startfrom=i", "device=s", "changer=s", "help" );
my $lsdvd = `which lsdvd`;
sub usage
{
print "Usage: $0\n" .
" -startfrom # - Slot # to start taking inventory from (default: 0)\n" .
" -device - device DVD Changer mounts DVDs as (deault: /dev/dvd2)\n" .
" -changer - DVD Changer device (deault: /dev/sg10)\n" .
" -location - Loation of stub files (default: /entertainment/changer)\n" .
" -help - Display this usage message\n";
print "ERROR: lsdvd is required. Please install and try again\n" if ( !$lsdvd );
exit;
}
usage() if ( !GetOptions( @optl ) || $opt_help || !$lsdvd );
$opt_startfrom = 0 if ( !$opt_startfrom );
$opt_device = "/dev/dvd2" if ( !$opt_device );
$opt_changer = "/dev/sg10" if ( !$opt_changer );
$opt_location = "/entertainment/changer" if ( !$opt_location );
my $osdcat = `which osd_cat`;
chomp( $osdcat );
$osdcat = "`" . $osdcat . " -w -p middle -d 1 -l 1 -A center -c yellow -O 5 -f -bitstream-bitstream\\ vera\\ sans\\ mono-bold-r-*-*-36-*-* " . $opt_location . "/loading.txt`\n" if ( $osdcat );
print "Unloading DVD changer...\n";
system("mythdvdchangerunload.sh");
print "Reading disc inventory...";
my $changerStatus = `mtx -f ${opt_changer} altres status`;
print "done\n";
my @changerStatus = split(/\n/, $changerStatus);
foreach( @changerStatus ) {
my $thisdisc;
my $ismounted;
if ( $_ =~ /Storage Element (\d+):Full/ )
{
my $slot = $1;
next if ( $slot < $opt_startfrom );
print "Slot #$slot has a disc. Loading disc for more information...";
system("mythdvdchangerload.sh ".$1);
my $count;
do {
$ismounted = `lsdvd ${opt_device} | grep 'Disc Title:'`;
if ( $ismounted ) {
$thisdisc = $1 if ( $ismounted =~ /Disc Title: (.*)/ );
}
$count++;
$thisdisc = "No Disc" if ( $count > 10 );
sleep 1;
} while ( !$thisdisc );
if ( $thisdisc ne "No Disc" ) {
print "Writing a stub file for: " . $thisdisc . "\n";
$thisdisc .= $slot if ( -e $opt_location . "/" . $thisdisc . ".stub" );
open (STUB, ">" . $opt_location . "/" . $thisdisc . ".stub");
my $stubfile = "#!/bin/bash\n" . $osdcat . "`mythdvdchangerload.sh " . $slot . "`\n`mplayer -fs -ao alsa -vo xv -dvd-device " . $opt_device . " dvdnav://`\n";
print STUB $stubfile;
close (STUB);
} else {
print "Could not read disc name after 10 seconds. Moving onto next disc...\n";
}
}
}
print "All done!\n";
exit;
If all goes well, you now have a directory filled with .stub files that represent each disc in your changer. Now go into MythVideo Settings and add a new filetype called "stub". The player command should be set to "sh" so MyhVideo knows to run it as a shell script. Then go into the MythVideo manager and scan for updates. Now you can add metadata to each file using your favorite lookup script (tmdb, etc.)
Now when you select a video from the list, the .stub file is executed which displays a loading message and issues the script to load the correct DVD and plays it with mplayer.
Ripping 200 DVDs at a Time
In addition to playing the disks off the drive, it is possible to use the unit as a "Batch Ripper." Go to this web site and click the "XL1B Media Download" link at the top. Also, install the prerequisite packages (Ubuntu Example):
apt-get install python mtx abcde lame cdparanoia id3v2 sg3-utils python-cddb wodim fakeroot
You will also need to install a copy of HandBrake if you wish to rip and compress at the same time.
Unzip the XL1B Media ZIP somewhere and change to that directory. Create a new file called "XL1B-DVD-RipCompress.py" and insert the following:
#! /usr/bin/python
import os, sys, time, commands, glob, re
modules_path = os.getcwd() + '/modules'
sys.path.append(modules_path)
import mtx_module as mtx
## author: Kevin Valentine
## email: kevin.valentine@gmail.com
## Adapted by Robert McNamara for transcoding (plus some cleanups)
## This small command line script will create an ISO image from all DVDs found
## in the XL1B2 changer's carousel. All ISOs will be stored in a new folder
## created in your home directory.
##
## Known dependencies:
## python mtx (<=1.3.11) sg3-utils
##
# This first path is the location where you want to store the encoded
# files. It defaults to using the operators home directory.
home_dir = '/MythMedia/rips'
path_changers = '/dev/sg*'
path_drives = '/dev/sr*'
scsi_changer = '/dev/sg4'
scsi_drive = '/dev/scd1'
descriptor_changer = 'VAIOChanger1 '
descriptor_drive = 'DVD-RAM SW-9584 '
# Set the device path of the changer mechanism
scsi_changer = mtx.find_device(path_changers, descriptor_changer)
print 'This CHANGER mechanism has been detected --> %s' %scsi_changer
# Set the device path of the drive mechanism
scsi_drive = mtx.find_device(path_drives, descriptor_drive)
print 'This DRIVE mechanism has been detected --> %s' %scsi_drive
# Define these globals after the attached devices
# have been detected and defined
changer_command = 'mtx -f %s nobarcode altres ' %scsi_changer
# isorip_command = "dd if=%s of=dvd.iso" %scsi_drive
def start_new_session():
print 'Any DVDs found in the changer will be automatically\nconverted to H.264/AC3 MKV files.\nThese files will be placed here:\n%s' %home_dir
return home_dir
def dvd_copy(slot, base_path):
start_time = time.time()
vol_ID_command = 'sleep 30 && fakeroot vol_id -L %s' %scsi_drive
vol_ID_string = commands.getstatusoutput(vol_ID_command)[1]
iso_path = '%s/%s' %(base_path, vol_ID_string)
isorip_command = "sleep 30 %% HandBrakeCLI -i /dev/scd1 -o \"%s.mkv\" -e x264 -q 0.600000023841858 -a 1 -E ac3 -B 160 -R Auto -6 auto -f mkv -p -m -x ref=3:mixed-refs:bframes=3:b pyramid:weightb:filter=-2,-1:trellis=1:analyse=all:8x8dct:me=umh:subme=9:psy-rd=1,1" %(iso_path)
print 'Running %s' %isorip_command
command_status = commands.getstatusoutput(isorip_command)
duration = (time.time() - start_time) / 60
print 'Slot %d has taken %.2f (min) to process.' %(slot, duration)
def main():
slot_status = mtx.get_status(changer_command, scsi_drive)
new_session_folder = start_new_session()
for n in range(len(slot_status)):
if slot_status[n]:
slot = n+1
mtx.load_CD(slot, changer_command)
dvd_copy(slot, new_session_folder)
mtx.unload_CD(slot, changer_command, scsi_drive)
if __name__ == '__main__':
main()
Edit the variables at the top to suit your destination. The drive devices *should* autodetect, but you can hard code these if necessary.
Save the file, and make it executable by running the following command on it:
chmod +x XL1B-DVD-RipCompress.py
You can now run the script and the ripping process should begin.
