From: <je...@us...> - 2003-07-30 21:50:21
|
Update of /cvsroot/quickrip/quickrip In directory sc8-pr-cvs1:/tmp/cvs-serv6391 Modified Files: dvd.py Log Message: Some code cleanup. Index: dvd.py =================================================================== RCS file: /cvsroot/quickrip/quickrip/dvd.py,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** dvd.py 30 Jul 2003 11:07:10 -0000 1.26 --- dvd.py 30 Jul 2003 21:48:15 -0000 1.27 *************** *** 14,492 **** class DVD: ! """Generic DVD functions for QuickRip: ! loadConfig() - load config file ! createConfig - create config file ! calcRate() - calculates a DivX bitrate ! scanDVD() - scans DVD for tracks, builds data structure ! ripDVD() - takes data structure and rips given tracks ! To use, inherit the class and provide the interface functions DVD() calls: ! int_startScanning() - notify user that the DVD is being scanned ! int_noTracks() - notify user that no tracks were found ! int_dispDVD() - display information about the DVD ! int_dispTrack() - display information about scanned track ! int_finishScanning() - notify user that scanning has finished ! int_startRipping() - notify user that ripping has started ! int_newTrack() - notify that ripping has begun on a new track ! int_newPass() - notify that new ripping pass has begun ! int_updateProgress() - update any ripping progress display being used ! int_finishRipping() - notify user that ripping has finished""" ! def __init__(self): ! self.cwd = os.getcwd() ! self.numtitles = 0 ! self.alangs = [] ! self.slangs = [] ! self.tracks = [] ! self.dio = {0 : 'None', 1: 'dint', 2: 'il', 3: 'lavcdeint', 4: 'pp=lb'} ! self.aro = {0: 'Default', 1: '4:3', 2: '16:9', 3: '2.35:1'} ! #self.configfile = os.path.expanduser("~") + "/.quickriprc" ! self.configfile = os.path.join(os.path.expanduser("~"), ".quickriprc") ! (self.config, self.parser) = self.loadConfig() ! def loadConfig(self): ! # Check config file exists ! if not os.path.isfile(self.configfile): ! self.createConfig() ! # Load configuration options from config file ! config = {} ! parser = ConfigParser.ConfigParser() ! parser.readfp(open(self.configfile, 'r')) ! config['mplayer'] = parser.get("paths", "mplayer") ! config['mencoder'] = parser.get("paths", "mencoder") ! config['tcprobe'] = parser.get("paths", "tcprobe") ! config['outputdir'] = parser.get("paths", "outputdir") ! config['deinterlacing'] = parser.get("mencoder", "deinterlacing") ! config['aspectratio'] = parser.get("mencoder", "aspectratio") ! # Upgrade old configs by catching exceptions ! try: ! config['passes'] = int(parser.get("mencoder", "passes")) ! except: ! config['passes'] = 0 ! parser.set("mencoder", "passes", 0) ! parser.write(open(self.configfile, 'w')) ! try: ! config['pdamode'] = parser.get("mencoder", "pdamode") ! except: ! config['pdamode'] = 0 ! parser.set("mencoder", "pdamode", 0) ! parser.write(open(self.configfile, 'w')) ! try: ! config['dvd_device'] = parser.get("paths", "dvd_device") ! except: ! config['dvd_device'] = os.path.join("/", "dev", "dvd") ! parser.set("paths", "dvd_device", config['dvd_device']) ! parser.write(open(self.configfile, 'w')) ! try: ! config['videocodec'] = parser.get("mencoder", "videocodec") ! except: ! config['videocodec'] = 0 ! parser.set("mencoder", "videocodec", 0) ! parser.write(open(self.configfile, 'w')) ! return (config, parser) ! def createConfig(self): ! # Find the programs mplayer, mencoder and tcprobe ! #paths = ['/usr/bin/', '/usr/local/bin/', '/opt/bin/', '/sbin/', '/usr/sbin/', '/bin', '/usr/X11R6/lib/X11/bin'] ! paths = config.paths ! mplayer, mencoder, tcprobe = "", "", "" ! for path in paths: ! #if os.path.isfile(path + "mplayer"): ! if os.path.isfile(os.path.join(path, "mplayer")): ! #mplayer = path + "mplayer" ! mplayer = os.path.join(path, "mplayer") ! #if os.path.isfile(path + "mencoder"): ! if os.path.isfile(os.path.join(path, "mencoder")): ! #mencoder = path + "mencoder" ! mencoder = os.path.join(path, "mencoder") ! if os.path.isfile(os.path.join(path, "tcprobe")): ! #tcprobe = path + "tcprobe" ! tcprobe = os.path.join(path, "tcprobe") ! if not mplayer:# == "": ! self.int_configError("mplayer") ! if not mencoder:# == "": ! self.int_configError("mencoder") ! if not tcprobe:# == "": ! self.int_configError("tcprobe") ! # Find home directory ! outdir = os.path.expanduser("~") ! dvd_device = os.path.join("/", "dev", "dvd") ! # Create config ! parser = ConfigParser.ConfigParser() ! parser.add_section("paths") ! parser.add_section("mencoder") ! parser.set("paths", "mplayer", mplayer) ! parser.set("paths", "mencoder", mencoder) ! parser.set("paths", "tcprobe", tcprobe) ! parser.set("paths", "dvd_device", dvd_device) ! parser.set("paths", "outputdir", outdir) ! parser.set("mencoder", "deinterlacing", 0) ! parser.set("mencoder", "aspectratio", 0) ! parser.set("mencoder", "passes", 3) ! parser.set("mencoder", "pdamode", 0) ! parser.set("mencoder", "videocodec", 0) ! parser.write(open(self.configfile, 'w')) ! def calcRate(self, length, audiobr, filesize): ! """Calculate bitrate for video based on: ! - length of track (seconds) ! - audio bitrate (kbps) ! - size of resultant file (MB)""" ! try: ! self.filesize = int(filesize) ! self.length = int(length) ! self.audiobr = int(audiobr) ! self.rate = ((self.filesize * 8192) / self.length) - self.audiobr ! self.rate = self.rate * 0.98 # Correction based on addition of credits and usual error ! return self.rate ! except: ! return 1 ! def calcFileSize(self, length, audiobr, bitrate): ! """Calculate vilesize for video based on: ! - length of track (seconds) ! - audio bitrate (kbps) ! - bitrate of track (Kbps)""" ! try: ! self.length = int(length) ! self.audiobr = int(audiobr) ! self.bitrate = int(bitrate) ! self.filesize = ((self.bitrate + self.audiobr) * self.length) / 8192 ! self.filesize = self.filesize * (1 / 0.98) # Correction based on addition of credits and usual error ! return self.filesize ! except: ! return 1 ! def scanDVD(self): ! """Scan DVD drive for titles with mplayer, and chapters and playback time with tcprobe""" ! self.int_startScanning() ! self.tracks = [] ! # Find number of tracks, audio languages and subtitle languages with MPlayer ! self.numtitles = 0 ! cmd_mplayer = "".join([str(self.config['mplayer']), ' -v dvd:// -identify -quiet -nocache 2>/dev/null']) ! text = os.popen(cmd_mplayer).readlines() ! del cmd_mplayer ! regexp_titl = re.compile('There are (\d.*) titles on this DVD') ! regexp_lang = re.compile('\[open\] audio stream:.*language: (\w*) aid.*') ! regexp_subt = re.compile('\[open\] subtitle.*language: (\w*)') ! for line in text: ! if regexp_titl.search(line): ! self.numtitles = regexp_titl.search(line).group(1) ! elif regexp_lang.search(line): ! lang = regexp_lang.search(line).group(1) ! if lang is 'unknown': ! lang = 'en' ! self.alangs.append(lang) ! elif regexp_subt.search(line): ! lang = regexp_subt.search(line).group(1) ! if lang is 'unknown': ! lang = 'en' ! self.slangs.append(lang) ! self.alangs.sort() ! self.slangs.sort() ! # Warn user of problems scanning drive ! if not self.numtitles:# == 0: ! self.int_noTracks() ! # Assume DVD is in english if nothing else ! # TODO: add default language to settings ! if not len(self.alangs):# == 0: ! self.alangs.append("en") ! self.int_dispDVD() ! # Run through tracks looking for playback times, chapters and cropping ! for i in range(int(self.numtitles) + 1): ! if i > 0: ! cmd_tcprobe = "".join([str(self.config['tcprobe']), " -i ", str(self.config['dvd_device']) + " -T ", str(i) + " 2>&1"]) ! text = os.popen(cmd_tcprobe).readlines() ! del cmd_tcprobe ! regexp_error = re.compile('No such file or directory') ! regexp_time = re.compile('.*title playback time: (.*):(.*):(\d*)\.\d* (\d*) sec') ! regexp_chap = re.compile('.*: (\d*) chapter.*') ! #regexp_scale = re.compile('.* (\d*x\d*) video.*') ! time_label = "" ! numchapters = 0 ! # Look for info in output, line by line ! for line in text: ! if regexp_error.search(line): ! self.int_noTracks() ! return ! if regexp_time.search(line): ! hours = regexp_time.search(line).group(1) ! minutes = regexp_time.search(line).group(2) ! seconds = regexp_time.search(line).group(3) ! time = regexp_time.search(line).group(4) ! time_label = "%2s hrs %2s mins %2s secs" % (hours, minutes, seconds) ! elif regexp_chap.search(line): ! numchapters = regexp_chap.search(line).group(1) ! #elif regexp_scale.search(line): ! # scale = regexp_scale.search(line).group(1) ! ! # Clean up title ! if i < 10: title_label = "".join(["0", str(i)]) ! else: title_label = str(i) ! # TODO ! # Find out length of each chapter ! # Set-up new track ! self.track = {} ! self.track['id'] = i ! self.track['name'] = title_label ! self.track['numchapters'] = int(numchapters) ! self.track['time'] = int(time) ! self.track['timelabel'] = time_label ! self.track['size'] = 680 ! self.track['abr'] = 96 ! self.track['abr_id'] = 1 ! self.track['vbr'] = self.calcRate(int(time), 96, 680) ! #self.track['scale'] = scale ! self.track['rip'] = "no" ! self.tracks.append(self.track) ! self.int_dispTrack(self.track) ! self.int_finishScanning() ! def ripDVD(self): ! """Rip the DVD based on the tracks data structure""" ! self.int_startRipping() ! self.state = "ripping" ! try: ! os.chdir(self.outdir) ! except OSError, msg: ! print "Unable to change to directory %s: %s" % (self.outdir, msg) ! # Build list of tracks to rip ! self.torip = [] ! for track in self.tracks: ! if track['rip'] == 'yes': ! self.torip.append(track) ! self.numrips = len(self.torip) ! # Check PDA mode (universal to all ripping methods) ! if int(self.config['pdamode']) == 0: ! resolution = "720" ! else: ! resolution = "320" ! # Run through selected tracks ripping each one ! i = 0 ! for item in self.torip: ! i = i + 1 ! self.track = item ! self.output = os.path.join(self.outdir, "".join([str(self.track['name']), ".avi"])) ! #self.output = re.sub(' ', '\\ ', self.output) # deprecated by making command a list ! self.int_newTrack(self.track['name'], i, self.numrips, self.track['vbr']) ! self.vol = "" ! self.volumead = str(self.volumead) ! if (self.volumead is not "0"): ! self.vol = "".join([":vol=", self.volumead]) ! ! # Look for cropping ! sstep = int(self.track['time']) / 31 ! if not sstep: ! sstep = 1 ! cmd = "".join(["mplayer -dvd ", str(self.track['id']), " -vop cropdetect -nosound -vo null -frames 10 -sstep ", str(sstep), " 2>/dev/null"]) ! text = os.popen(cmd).readlines() ! regexp = re.compile('.*-vop crop=(\d*:\d*:\d*:\d*).*') ! crop_options = {} ! common_crop = "" ! cc_hits = 0 ! for line in text: ! if regexp.search(line): ! crop = regexp.search(line).group(1) ! try: ! crop_options[crop] = crop_options[crop] + 1 ! if crop_options[crop] > cc_hits: ! common_crop = crop ! except: ! crop_options[crop] = 1 ! self.track['crop'] = common_crop ! # Clean up output dir in case QuickRip crashed out there ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! lameopts = "".join(["cbr=", str(self.track['abr']), str(self.vol)]) ! if self.config['videocodec']: ! ovc = "xvid" ! ovc_opts_type = "-xvidencopts" ! ovc_opts = "".join(["4mv:me_quality=6:mod_quant:quant_range=1-31/1-31:bitrate=", str(int(self.track['vbr']))]) ! else: ! ovc = "lavc" ! ovc_opts_type = "-lavcopts" ! ovc_opts = "".join(["vcodec=mpeg4:vhq:vbitrate=", str(int(self.track['vbr']))]) ! vop = "".join(["scale,crop=",self.track['crop']]) ! if int(self.config['deinterlacing']) is not 0: ! vop = "".join([vop, ",", self.dio[self.config['deinterlacing']]]) ! if self.config['passes'] is 1: ! all_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", ovc, ovc_opts_type, ovc_opts, "-vop", vop, "-zoom", \ ! "-xy", resolution, "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! all_pass.insert(3, "-aspect") ! all_pass.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! all_pass.insert(3, "-slang") ! all_pass.insert(4, self.sLanguage) ! # Uncomment to test command ! string = "" ! for bit in all_pass: ! bit = "".join([" ", bit]) ! string = "".join([string, bit]) ! print all_pass ! print string ! # sys.exit(1) ! self.runPass("audio", all_pass) ! elif not self.config['passes'] or self.config['passes'] is 2: ! audio_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", "frameno", "-o", \ ! "".join([self.outdir, "frameno.avi"]), "2>/dev/null"] ! video_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, ovc_opts, "-vop", vop, "-zoom", "-xy", resolution, \ ! "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! video_pass.insert(3, "-aspect") ! video_pass.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! video_pass.insert(3, "-slang") ! video_pass.insert(4, self.sLanguage) ! # Uncomment to test command ! string1 = "" ! string2 = "" ! for bit in audio_pass: ! bit = "".join([" ", str(bit)]) ! string1 = "".join([string1, bit]) ! for bit in video_pass: ! bit = "".join([" ", str(bit)]) ! string2 = "".join([string2, bit]) ! print string1 ! print string2 ! # sys.exit(1) ! self.runPass("audio", audio_pass) ! self.runPass("video1", video_pass) ! os.popen("rm divx2pass.log 2>/dev/null") ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! elif self.config['passes'] is 3: ! audio_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", "frameno", "-o", \ ! "".join([self.outdir, "frameno.avi"]), "2>/dev/null"] ! video_pass1 = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, "".join([ovc_opts, ":vpass=1"]), "-vop", vop, \ ! "-zoom", "-xy", resolution, "-o", self.output, "2>/dev/null"] ! video_pass2 = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, "".join([ovc_opts, ":vpass=2"]), "-vop", vop, \ ! "-zoom", "-xy", resolution, "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! video_pass1.insert(3, "-aspect") ! video_pass1.insert(4, self.aro[self.config['aspectratio']]) ! video_pass2.insert(3, "-aspect") ! video_pass2.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! video_pass1.insert(3, "-slang") ! video_pass1.insert(4, self.sLanguage) ! video_pass2.insert(3, "-slang") ! video_pass2.insert(4, self.sLanguage) ! self.runPass("audio", audio_pass) ! self.runPass("video1", video_pass1) ! self.runPass("video2", video_pass2) ! ! os.popen("rm divx2pass.log 2>/dev/null") ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! os.chdir(self.cwd) ! self.int_finishRipping() ! def runPass(self, name, command): ! # Nasty GUI-specific code to stop GUI running on to other passes when previous ! # pass was cleanly stopped (without exiting the whole program) ! if self.state is "stopped": ! return ! pipe_perc = re.compile('.*f \((.\d)\%\)*') ! pipe_Trem = re.compile('(?P<int>[0-9]+)min') ! perc = 0 ! Trem = 0 ! self.int_newPass(name) ! self.pipe = popen2.Popen4(command) ! pid = self.pipe.pid ! while 1: ! line = self.pipe.fromchild.read(1000) ! if not line:# == '': ! break ! if pipe_perc.search(line): ! perc = pipe_perc.search(line).group(1) ! perc = re.sub(' ', '', perc) ! if pipe_Trem.search(line): ! Trem = pipe_Trem.search(line).group(0) ! self.int_updateProgress(perc, Trem, name) ! os.waitpid(pid, os.WNOHANG) ! ## INHERIT THE CLASS AND SUBSTITUE THESE CLASS METHODS WITH YOUR ! ## OWN UI HOOKS ! def int_startScanning(self): ! pass ! def int_noTracks(self): ! pass ! def int_dispDVD(self): ! pass ! def int_dispTrack(self, track): ! pass ! def int_finishScanning(self): ! pass ! def int_startRipping(self): ! pass ! def int_newTrack(self, name, number, total, vbr): ! pass ! def int_newPass(self, passtype): ! pass ! def int_updateProgress(self, perc, tpass): ! pass ! def int_finishRipping(self): ! pass --- 14,486 ---- class DVD: ! """Generic DVD functions for QuickRip: ! loadConfig() - load config file ! createConfig - create config file ! calcRate() - calculates a DivX bitrate ! scanDVD() - scans DVD for tracks, builds data structure ! ripDVD() - takes data structure and rips given tracks ! To use, inherit the class and provide the interface functions DVD() calls: ! int_startScanning() - notify user that the DVD is being scanned ! int_noTracks() - notify user that no tracks were found ! int_dispDVD() - display information about the DVD ! int_dispTrack() - display information about scanned track ! int_finishScanning() - notify user that scanning has finished ! int_startRipping() - notify user that ripping has started ! int_newTrack() - notify that ripping has begun on a new track ! int_newPass() - notify that new ripping pass has begun ! int_updateProgress() - update any ripping progress display being used ! int_finishRipping() - notify user that ripping has finished""" ! def __init__(self): ! self.cwd = os.getcwd() ! self.numtitles = 0 ! self.alangs = [] ! self.slangs = [] ! self.tracks = [] ! self.dio = {0 : 'None', 1: 'dint', 2: 'il', 3: 'lavcdeint', 4: 'pp=lb'} ! self.aro = {0: 'Default', 1: '4:3', 2: '16:9', 3: '2.35:1'} ! #self.configfile = os.path.expanduser("~") + "/.quickriprc" ! self.configfile = os.path.join(os.path.expanduser("~"), ".quickriprc") ! (self.config, self.parser) = self.loadConfig() ! def loadConfig(self): ! # Check config file exists ! if not os.path.isfile(self.configfile): ! self.createConfig() ! # Load configuration options from config file ! config = {} ! parser = ConfigParser.ConfigParser() ! parser.readfp(open(self.configfile, 'r')) ! config['mplayer'] = parser.get("paths", "mplayer") ! config['mencoder'] = parser.get("paths", "mencoder") ! config['tcprobe'] = parser.get("paths", "tcprobe") ! config['outputdir'] = parser.get("paths", "outputdir") ! config['deinterlacing'] = parser.get("mencoder", "deinterlacing") ! config['aspectratio'] = parser.get("mencoder", "aspectratio") ! # Upgrade old configs by catching exceptions ! try: ! config['passes'] = int(parser.get("mencoder", "passes")) ! except: ! config['passes'] = 0 ! parser.set("mencoder", "passes", 0) ! parser.write(open(self.configfile, 'w')) ! try: ! config['pdamode'] = parser.get("mencoder", "pdamode") ! except: ! config['pdamode'] = 0 ! parser.set("mencoder", "pdamode", 0) ! parser.write(open(self.configfile, 'w')) ! try: ! config['dvd_device'] = parser.get("paths", "dvd_device") ! except: ! config['dvd_device'] = os.path.join("/", "dev", "dvd") ! parser.set("paths", "dvd_device", config['dvd_device']) ! parser.write(open(self.configfile, 'w')) ! try: ! config['videocodec'] = parser.get("mencoder", "videocodec") ! except: ! config['videocodec'] = 0 ! parser.set("mencoder", "videocodec", 0) ! parser.write(open(self.configfile, 'w')) ! return (config, parser) ! def createConfig(self): ! # Find the programs mplayer, mencoder and tcprobe ! paths = config.paths ! mplayer, mencoder, tcprobe = "", "", "" ! for path in paths: ! if os.path.isfile(os.path.join(path, "mplayer")): ! mplayer = os.path.join(path, "mplayer") ! if os.path.isfile(os.path.join(path, "mencoder")): ! mencoder = os.path.join(path, "mencoder") ! if os.path.isfile(os.path.join(path, "tcprobe")): ! tcprobe = os.path.join(path, "tcprobe") ! if not mplayer: ! self.int_configError("mplayer") ! if not mencoder: ! self.int_configError("mencoder") ! if not tcprobe: ! self.int_configError("tcprobe") ! # Find home directory ! outdir = os.path.expanduser("~") ! dvd_device = os.path.join("/", "dev", "dvd") ! # Create config ! parser = ConfigParser.ConfigParser() ! parser.add_section("paths") ! parser.add_section("mencoder") ! parser.set("paths", "mplayer", mplayer) ! parser.set("paths", "mencoder", mencoder) ! parser.set("paths", "tcprobe", tcprobe) ! parser.set("paths", "dvd_device", dvd_device) ! parser.set("paths", "outputdir", outdir) ! parser.set("mencoder", "deinterlacing", 0) ! parser.set("mencoder", "aspectratio", 0) ! parser.set("mencoder", "passes", 3) ! parser.set("mencoder", "pdamode", 0) ! parser.set("mencoder", "videocodec", 0) ! parser.write(open(self.configfile, 'w')) ! def calcRate(self, length, audiobr, filesize): ! """Calculate bitrate for video based on: ! - length of track (seconds) ! - audio bitrate (kbps) ! - size of resultant file (MB)""" ! try: ! self.filesize = int(filesize) ! self.length = int(length) ! self.audiobr = int(audiobr) ! self.rate = ((self.filesize * 8192) / self.length) - self.audiobr ! self.rate = self.rate * 0.98 # Correction based on addition of credits and usual error ! return self.rate ! except: ! return 1 ! def calcFileSize(self, length, audiobr, bitrate): ! """Calculate vilesize for video based on: ! - length of track (seconds) ! - audio bitrate (kbps) ! - bitrate of track (Kbps)""" ! try: ! self.length = int(length) ! self.audiobr = int(audiobr) ! self.bitrate = int(bitrate) ! self.filesize = ((self.bitrate + self.audiobr) * self.length) / 8192 ! self.filesize = self.filesize * (1 / 0.98) # Correction based on addition of credits and usual error ! return self.filesize ! except: ! return 1 ! def scanDVD(self): ! """Scan DVD drive for titles with mplayer, and chapters and playback time with tcprobe""" ! self.int_startScanning() ! self.tracks = [] ! # Find number of tracks, audio languages and subtitle languages with MPlayer ! self.numtitles = 0 ! cmd_mplayer = "".join([str(self.config['mplayer']), ' -v dvd:// -identify -quiet -nocache 2>/dev/null']) ! text = os.popen(cmd_mplayer).readlines() ! del cmd_mplayer ! regexp_titl = re.compile('There are (\d.*) titles on this DVD') ! regexp_lang = re.compile('\[open\] audio stream:.*language: (\w*) aid.*') ! regexp_subt = re.compile('\[open\] subtitle.*language: (\w*)') ! for line in text: ! if regexp_titl.search(line): ! self.numtitles = regexp_titl.search(line).group(1) ! elif regexp_lang.search(line): ! lang = regexp_lang.search(line).group(1) ! if lang is 'unknown': ! lang = 'en' ! self.alangs.append(lang) ! elif regexp_subt.search(line): ! lang = regexp_subt.search(line).group(1) ! if lang is 'unknown': ! lang = 'en' ! self.slangs.append(lang) ! self.alangs.sort() ! self.slangs.sort() ! # Warn user of problems scanning drive ! if not self.numtitles: ! self.int_noTracks() ! # Assume DVD is in english if nothing else ! # TODO: add default language to settings ! if not len(self.alangs): ! self.alangs.append("en") ! self.int_dispDVD() ! # Run through tracks looking for playback times, chapters and cropping ! for i in range(int(self.numtitles) + 1): ! if i > 0: ! cmd_tcprobe = "".join([str(self.config['tcprobe']), " -i ", str(self.config['dvd_device']) + " -T ", str(i) + " 2>&1"]) ! text = os.popen(cmd_tcprobe).readlines() ! del cmd_tcprobe ! regexp_error = re.compile('No such file or directory') ! regexp_time = re.compile('.*title playback time: (.*):(.*):(\d*)\.\d* (\d*) sec') ! regexp_chap = re.compile('.*: (\d*) chapter.*') ! #regexp_scale = re.compile('.* (\d*x\d*) video.*') ! time_label = "" ! numchapters = 0 ! # Look for info in output, line by line ! for line in text: ! if regexp_error.search(line): ! self.int_noTracks() ! return ! if regexp_time.search(line): ! hours = regexp_time.search(line).group(1) ! minutes = regexp_time.search(line).group(2) ! seconds = regexp_time.search(line).group(3) ! time = regexp_time.search(line).group(4) ! time_label = "%2s hrs %2s mins %2s secs" % (hours, minutes, seconds) ! elif regexp_chap.search(line): ! numchapters = regexp_chap.search(line).group(1) ! #elif regexp_scale.search(line): ! # scale = regexp_scale.search(line).group(1) ! ! # Clean up title ! if i < 10: title_label = "".join(["0", str(i)]) ! else: title_label = str(i) ! # TODO ! # Find out length of each chapter ! # Set-up new track ! self.track = {} ! self.track['id'] = i ! self.track['name'] = title_label ! self.track['numchapters'] = int(numchapters) ! self.track['time'] = int(time) ! self.track['timelabel'] = time_label ! self.track['size'] = 680 ! self.track['abr'] = 96 ! self.track['abr_id'] = 1 ! self.track['vbr'] = self.calcRate(int(time), 96, 680) ! #self.track['scale'] = scale ! self.track['rip'] = "no" ! self.tracks.append(self.track) ! self.int_dispTrack(self.track) ! self.int_finishScanning() ! def ripDVD(self): ! """Rip the DVD based on the tracks data structure""" ! self.int_startRipping() ! self.state = "ripping" ! try: ! os.chdir(self.outdir) ! except OSError, msg: ! print "Unable to change to directory %s: %s" % (self.outdir, msg) ! # Build list of tracks to rip ! self.torip = [] ! for track in self.tracks: ! if track['rip'] == 'yes': ! self.torip.append(track) ! self.numrips = len(self.torip) ! # Check PDA mode (universal to all ripping methods) ! if int(self.config['pdamode']) == 0: ! resolution = "720" ! else: ! resolution = "320" ! # Run through selected tracks ripping each one ! i = 0 ! for item in self.torip: ! i = i + 1 ! self.track = item ! self.output = os.path.join(self.outdir, "".join([str(self.track['name']), ".avi"])) ! #self.output = re.sub(' ', '\\ ', self.output) # deprecated by making command a list ! self.int_newTrack(self.track['name'], i, self.numrips, self.track['vbr']) ! self.vol = "" ! self.volumead = str(self.volumead) ! if (self.volumead is not "0"): ! self.vol = "".join([":vol=", self.volumead]) ! ! # Look for cropping ! sstep = int(self.track['time']) / 31 ! if not sstep: ! sstep = 1 ! cmd = "".join(["mplayer -dvd ", str(self.track['id']), " -vop cropdetect -nosound -vo null -frames 10 -sstep ", str(sstep), " 2>/dev/null"]) ! text = os.popen(cmd).readlines() ! regexp = re.compile('.*-vop crop=(\d*:\d*:\d*:\d*).*') ! crop_options = {} ! common_crop = "" ! cc_hits = 0 ! for line in text: ! if regexp.search(line): ! crop = regexp.search(line).group(1) ! try: ! crop_options[crop] = crop_options[crop] + 1 ! if crop_options[crop] > cc_hits: ! common_crop = crop ! except: ! crop_options[crop] = 1 ! self.track['crop'] = common_crop ! # Clean up output dir in case QuickRip crashed out there ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! lameopts = "".join(["cbr=", str(self.track['abr']), str(self.vol)]) ! if self.config['videocodec']: ! ovc = "xvid" ! ovc_opts_type = "-xvidencopts" ! ovc_opts = "".join(["4mv:me_quality=6:mod_quant:quant_range=1-31/1-31:bitrate=", str(int(self.track['vbr']))]) ! else: ! ovc = "lavc" ! ovc_opts_type = "-lavcopts" ! ovc_opts = "".join(["vcodec=mpeg4:vhq:vbitrate=", str(int(self.track['vbr']))]) ! vop = "".join(["scale,crop=",self.track['crop']]) ! if int(self.config['deinterlacing']) is not 0: ! vop = "".join([vop, ",", self.dio[self.config['deinterlacing']]]) ! if self.config['passes'] is 1: ! all_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", ovc, ovc_opts_type, ovc_opts, "-vop", vop, "-zoom", \ ! "-xy", resolution, "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! all_pass.insert(3, "-aspect") ! all_pass.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! all_pass.insert(3, "-slang") ! all_pass.insert(4, self.sLanguage) ! # Uncomment to test command ! string = "" ! for bit in all_pass: ! bit = "".join([" ", bit]) ! string = "".join([string, bit]) ! print all_pass ! print string ! # sys.exit(1) ! self.runPass("audio", all_pass) ! elif not self.config['passes'] or self.config['passes'] is 2: ! audio_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", "frameno", "-o", \ ! "".join([self.outdir, "frameno.avi"]), "2>/dev/null"] ! video_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, ovc_opts, "-vop", vop, "-zoom", "-xy", resolution, \ ! "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! video_pass.insert(3, "-aspect") ! video_pass.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! video_pass.insert(3, "-slang") ! video_pass.insert(4, self.sLanguage) ! # Uncomment to test command ! string1 = "" ! string2 = "" ! for bit in audio_pass: ! bit = "".join([" ", str(bit)]) ! string1 = "".join([string1, bit]) ! for bit in video_pass: ! bit = "".join([" ", str(bit)]) ! string2 = "".join([string2, bit]) ! print string1 ! print string2 ! # sys.exit(1) ! self.runPass("audio", audio_pass) ! self.runPass("video1", video_pass) ! os.popen("rm divx2pass.log 2>/dev/null") ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! elif self.config['passes'] is 3: ! audio_pass = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-oac", "mp3lame", "-lameopts", lameopts, "-ovc", "frameno", "-o", \ ! "".join([self.outdir, "frameno.avi"]), "2>/dev/null"] ! video_pass1 = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, "".join([ovc_opts, ":vpass=1"]), "-vop", vop, \ ! "-zoom", "-xy", resolution, "-o", self.output, "2>/dev/null"] ! video_pass2 = [str(self.config['mencoder']), "-dvd", str(self.track['id']), "-alang", self.aLanguage, \ ! "-sws", "2", "-oac", "copy", "-ovc", ovc, ovc_opts_type, "".join([ovc_opts, ":vpass=2"]), "-vop", vop, \ ! "-zoom", "-xy", resolution, "-o", self.output, "2>/dev/null"] ! if int(self.config['aspectratio']) is not 0: ! video_pass1.insert(3, "-aspect") ! video_pass1.insert(4, self.aro[self.config['aspectratio']]) ! video_pass2.insert(3, "-aspect") ! video_pass2.insert(4, self.aro[self.config['aspectratio']]) ! if self.sLanguage is not "None": ! video_pass1.insert(3, "-slang") ! video_pass1.insert(4, self.sLanguage) ! video_pass2.insert(3, "-slang") ! video_pass2.insert(4, self.sLanguage) ! self.runPass("audio", audio_pass) ! self.runPass("video1", video_pass1) ! self.runPass("video2", video_pass2) ! ! os.popen("rm divx2pass.log 2>/dev/null") ! os.popen("".join(["rm ", self.outdir, "frameno.avi 2>/dev/null"])) ! os.chdir(self.cwd) ! self.int_finishRipping() ! def runPass(self, name, command): ! # Nasty GUI-specific code to stop GUI running on to other passes when previous ! # pass was cleanly stopped (without exiting the whole program) ! if self.state is "stopped": ! return ! pipe_perc = re.compile('.*f \((.\d)\%\)*') ! pipe_Trem = re.compile('(?P<int>[0-9]+)min') ! perc = 0 ! Trem = 0 ! self.int_newPass(name) ! self.pipe = popen2.Popen4(command) ! pid = self.pipe.pid ! while 1: ! line = self.pipe.fromchild.read(1000) ! if not line:# == '': ! break ! if pipe_perc.search(line): ! perc = pipe_perc.search(line).group(1) ! perc = re.sub(' ', '', perc) ! if pipe_Trem.search(line): ! Trem = pipe_Trem.search(line).group(0) ! self.int_updateProgress(perc, Trem, name) ! os.waitpid(pid, os.WNOHANG) ! ## INHERIT THE CLASS AND SUBSTITUE THESE CLASS METHODS WITH YOUR ! ## OWN UI HOOKS ! def int_startScanning(self): ! pass ! def int_noTracks(self): ! pass ! def int_dispDVD(self): ! pass ! def int_dispTrack(self, track): ! pass ! def int_finishScanning(self): ! pass ! def int_startRipping(self): ! pass ! def int_newTrack(self, name, number, total, vbr): ! pass ! def int_newPass(self, passtype): ! pass ! def int_updateProgress(self, perc, tpass): ! pass ! def int_finishRipping(self): ! pass |