def kill(job, signal='-KILL'):
    pid = str(job['pid'])
    plugin.log(plugin.lang(50019) % (job['dev'], signal)) #killing makemkvcon job on %s with signal %s
    cmd = ['kill', signal, pid]
    subprocess.call(cmd)
    if signal == '-KILL':
        if job['tmp_dir'] is not None:
            cleanup(job)
def installed():
    path = plugin.get('makemkvcon_path', 'makemkvcon')
    plugin.log('makemkvcon_path = %s' % path)
    try:
        p = subprocess.Popen(path, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        p = None
        return True
    except Exception, e:
        plugin.log(plugin.lang(50017) % e.strerror) #makemkvcon.installed() ERROR: %s
def start(job):

    job['tmp_dir'] = tempfile.mkdtemp(suffix='.mkvripper', dir=job['dest_writepath'])

    ripsize_min = plugin.get('ripsize_min', '600')

    cmd = plugin.get('makemkvcon_path', 'makemkvcon')
    cmd = [cmd, '-r', '--progress=-stdout', '--minlength=%s' % ripsize_min, 
           'mkv', 'dev:%s' % job['dev'], 'all', job['tmp_dir']]
    job['cmd'] = cmd
    job['output'] = subprocess.Popen(job['cmd'], 
    stdout=subprocess.PIPE, stderr=subprocess.PIPE,
    close_fds=True)

    job['pid'] = job['output'].pid
    plugin.log(plugin.lang(50021) % job['cmd']) #started new makemkvcon with command %s
    return job
def save(job):

    if not running():
        l = os.listdir(job['tmp_dir'])
        if l == []:
            cleanup(job)
	    raise TmpDirEmpty('temporary directory empty!')
        for i in l:

            src = os.path.join(job['tmp_dir'], i)
            if len(l) >= 2:
                dest = os.path.join(job['dest_writepath'], job['dest_savename'] + i[-6:]) #save as numbered .mkv file if there is more than one file to be saved
            else:
                dest = os.path.join(job['dest_writepath'], job['dest_savename'] + i[-4:]) #save without numbered suffix if only one .mkv file to be saved

            try:
                shutil.move(src, dest)
            except Exception, e:
                plugin.log(plugin.lang(50022) % e.strerror) #makemkvcon.save() ERROR: %s
                cleanup(job)
                raise
        cleanup(job)
# Addon info
__addon__     = xbmcaddon.Addon()
__cwd__       = __addon__.getAddonInfo('path')
sys.path.append(xbmc.translatePath(os.path.join(__cwd__, 'resources', 'lib')))

# Local imports
import plugin, makemkv, makemkvcon
plugin.log('starting service')

# Settings
BDDIR = 'BDMV'

# Check for makemkvcon
if not makemkvcon.installed():
  plugin.notify(plugin.lang(50001))

# Service loop
key_checked  = 0
disc_current = None
disc_started = 0
disc_ready   = False
while not xbmc.abortRequested:
  plugin.log('run')

  # Update fixed key
  key = plugin.get('license_key')
  if key:
    makemkv.set(makemkv.APP_KEY, key)

  # Check for beta key
        tmp = urlparse.parse_qs(sys.argv[2][1:])
        for k in tmp:
            ret[k] = tmp[k][0]
    return ret


# Play a title
def playTitle(title):
    plugin.log('playing %s' % title['file0'])
    xbmc.executebuiltin('PlayMedia("%s")' % title['file0'])


# Check installed
plugin.log('checking makemkvcon installed')
if not makemkvcon.installed():
    plugin.notify(plugin.lang(50001))
    sys.exit(1)

# Start
makemkvcon.start()

# Check that service is running
st = time.time()
ok = False
# TODO: dialog
while not ok and (time.time() - st) < plugin.get_int('disc_timeout'):
    plugin.log('waiting for makemkvcon')
    ok = makemkvcon.ready()
    time.sleep(0.5)
if not ok:
    plugin.notify(plugin.lang(50006))
  ret = {}
  if sys.argv[2].startswith('?'):
    tmp = urlparse.parse_qs(sys.argv[2][1:])
    for k in tmp:
      ret[k] = tmp[k][0]
  return ret

# Play a title
def playTitle ( title ):
  plugin.log('playing %s' % title['file0'])
  xbmc.executebuiltin('PlayMedia("%s")' % title['file0'])

# Check installed
plugin.log('checking makemkvcon installed')
if not makemkvcon.installed():
  plugin.notify(plugin.lang(50001))
  sys.exit(1)

# Start
makemkvcon.start()
    
# Check that service is running
st = time.time()
ok = False
# TODO: dialog
while not ok and (time.time() - st) < plugin.get_int('disc_timeout'):
  plugin.log('waiting for makemkvcon')
  ok = makemkvcon.ready()
  time.sleep(0.5)
if not ok:
  plugin.notify(plugin.lang(50006))
def cleanup(job):
    tmp_dir = job['tmp_dir']
    try:
        shutil.rmtree(tmp_dir)
    except Exception, e:
        plugin.log(plugin.lang(50018) % e.strerror) #makemkvcon.cleanup() ERROR: %s
    def __init__(self):

        global MAKEMKVCON
        dialog = xbmcgui.Dialog()

        if not makemkvcon.installed():
            plugin.log(plugin.lang(50008)) #makemkvcon binary not found

            if dialog.ok(plugin.lang(50015), plugin.lang(50008)): #makemkvcon binary not found. Install MakeMKV or adjust makemkvcon binary path setting.
                self.close()
                return

        job = {}
        job['dev'] = plugin.get('disc_number', '/dev/sr0') #configurable in settings

        starting = dialog.yesno(__addonname__, plugin.lang(50011) % job['dev']) #Rip media from disc on <disc>?
        if starting:

            #is cdrom Device?
            info = open('/proc/sys/dev/cdrom/info').read()
            dev = job['dev'].split('/')[-1] 
            if dev not in info:
                if dialog.ok(plugin.lang(50015), plugin.lang(50002)): #Disc drive device file not reported as CDROM device. Adjust disc drive device file setting.
                    self.close()
                    return

            job_running = makemkvcon.running(job['dev'])

            if job_running:
                if dialog.yesno(__addonname__, plugin.lang(50012) % job['dev'], nolabel=plugin.lang(52001), yeslabel=plugin.lang(52002)): #Rip operation already running on <disc>. Cancel running operation and start over or exit?
                    job['pid'] = job_running
                    makemkvcon.kill(job)
                else:
                    plugin.log(plugin.lang(50010)) #User did not select a disc rip operation.
                    self.close()
                    return

            while True:
                job['dest_writepath'] = dialog.browse(3, plugin.lang(51001), 'video', '', False, False, '')
                if job['dest_writepath'] == '':
                    self.close()
                    return

                kb = xbmc.Keyboard('', plugin.lang(51002)) 
                kb.doModal()
                if kb.isConfirmed():
                    job['dest_savename'] = kb.getText()
                    if job['dest_savename'] == '':
                        job['dest_savename'] = plugin.lang(51003) #title.mkv for single file or titleXX.mkv for multiple files are default savenames
                    break

            p_dialog = xbmcgui.DialogProgress()
            MAKEMKVCON = makemkvcon.start(job)
            p_dialog.create(__addonname__, plugin.lang(50005) % MAKEMKVCON['dev']) #Scanning media in <disc>
            pipe = MAKEMKVCON['output']
            label = plugin.lang(50006) % MAKEMKVCON['dev'] #Ripping files from media in <disc>
            percent = 0
            
            while True:
                line = pipe.stdout.readline()
                if not line:
                    break

                if line.startswith('MSG:'):
                    msg = line.split('"')[1]
                    if line.startswith('MSG:5038'):        #Disc space error; is a prompt.
                        makemkvcon.kill(MAKEMKVCON, '-STOP')
                        if dialog.yesno(__addonname__, msg):
                            line = ''      
                            makemkvcon.kill(MAKEMKVCON, '-CONT')
                        else:
                            sys.stdout.flush()
                            makemkvcon.kill(MAKEMKVCON)
                            MAKEMKVCON = None
                            self.close()
                            return
                    if line.startswith('MSG:5010'):         #Failed to open disc error. Can stem from a number of things such as tray status and inserted media type.
                        makemkvcon.kill(MAKEMKVCON, '-STOP')
                        msg = 'makemkvcon: %s %s' % (msg, plugin.lang(50004)) #Failed to open disc, ensure correct media inserted and device tray closed.
                        if dialog.ok(plugin.lang(50015), msg): 
                            sys.stdout.flush()
                            makemkvcon.kill(MAKEMKVCON)
                            MAKEMKVCON = None
                            self.close()
                            return
                    if msg.startswith('Error'):             #Kind of a lame way to catch an error, but reading makemkvcon's output works for HDD space issues as well as tray issues.
                        makemkvcon.kill(MAKEMKVCON, '-STOP')
                        msg = 'makemkvcon: %s' % msg
                        if dialog.ok(plugin.lang(50015), msg): 
                            sys.stdout.flush()
                            makemkvcon.kill(MAKEMKVCON)
                            MAKEMKVCON = None
                            self.close()
                            return

                if line.startswith('PRGV:'):        #Monitor rip progress for progress bar
                    line = line.split(',')
                    n = float(line[1])
                    d = float(line[2])
                    percent = int(n / d * 100)

                if p_dialog.iscanceled():
                    makemkvcon.kill(MAKEMKVCON, '-STOP')
                    if dialog.yesno(__addonname__, plugin.lang(50003) % MAKEMKVCON['dev']): #Cancel rip operation on <disc>?
                        makemkvcon.kill(MAKEMKVCON)
                        MAKEMKVCON = None
                        p_dialog.close()
                        self.close()
                        return
                    else:
                        makemkvcon.kill(MAKEMKVCON, '-CONT')
                        p_dialog.create(__addonname__, plugin.lang(50005) % MAKEMKVCON['dev']) #Scanning media in <disc>

                p_dialog.update(percent, label, msg)
                sys.stdout.flush()

            p_dialog.update(100, plugin.lang(50016) % MAKEMKVCON['dest_writepath']) #Moving titles from temporary directory to <savedir>
            try:
                makemkvcon.save(MAKEMKVCON)
            except makemkvcon.TmpDirEmpty:				#Is temporary directory empty after rip has completed successfully?
		if dialog.ok(plugin.lang(50015), plugin.lang(50023)): 	#Plugin detected that makemkvcon ripped no files but exited successfully.
                    self.close()
                    return
            except Exception, e:								#some other error with shutil.move()
                if dialog.ok(plugin.lang(50015), e.strerror):
                    self.close()
                    return
                
            plugin.notify(plugin.lang(50013) % (MAKEMKVCON['dev'], MAKEMKVCON['dest_writepath']), timeout=10000) #Rip finished on <disc>. New files in <savedir>
            MAKEMKVCON = None
                        self.close()
                        return
                    else:
                        makemkvcon.kill(MAKEMKVCON, '-CONT')
                        p_dialog.create(__addonname__, plugin.lang(50005) % MAKEMKVCON['dev']) #Scanning media in <disc>

                p_dialog.update(percent, label, msg)
                sys.stdout.flush()

            p_dialog.update(100, plugin.lang(50016) % MAKEMKVCON['dest_writepath']) #Moving titles from temporary directory to <savedir>
            try:
                makemkvcon.save(MAKEMKVCON)
            except makemkvcon.TmpDirEmpty:				#Is temporary directory empty after rip has completed successfully?
		if dialog.ok(plugin.lang(50015), plugin.lang(50023)): 	#Plugin detected that makemkvcon ripped no files but exited successfully.
                    self.close()
                    return
            except Exception, e:								#some other error with shutil.move()
                if dialog.ok(plugin.lang(50015), e.strerror):
                    self.close()
                    return
                
            plugin.notify(plugin.lang(50013) % (MAKEMKVCON['dev'], MAKEMKVCON['dest_writepath']), timeout=10000) #Rip finished on <disc>. New files in <savedir>
            MAKEMKVCON = None
        else:
            plugin.log(plugin.lang(50010)) #User did not select a disc rip operation.
            self.close()

    def onAction(self, action):
        if action == ACTION_PREVIOUS_MENU or KEY_BUTTON_BACK:
            self.close()
Example #11
0
# Addon info
__addon__     = xbmcaddon.Addon()
__cwd__       = __addon__.getAddonInfo('path')
sys.path.append(xbmc.translatePath(os.path.join(__cwd__, 'lib')))

# Local imports
import plugin, makemkv, makemkvcon
plugin.log('starting service')

# Settings
BDDIR = 'BDMV'

# Check for makemkvcon
if not makemkvcon.installed():
  plugin.notify(plugin.lang(50001))

# Config
for k in [ 'license_key', 'license_beta_auto', 'license_beta_period', 'disc_autoload', 'disc_autostart', 'disc_timeout' ]:
  v = plugin.get(k)
  plugin.log('config %s => %s' % (k, v))

# Service loop
key_checked  = 0
disc_current = None
disc_started = 0
disc_ready   = False
while not xbmc.abortRequested:

  # Update fixed key
  key = plugin.get('license_key')