parameters: ()
return_statement: return True
docstring: Support mirobridge from the command line
      returns True
docstring_summary: Support mirobridge from the command line
      returns True
docstring_tokens: Support mirobridge from the command line returns True
function: def main():
      """Support mirobridge from the command line
      returns True
      """
      global localhostname, simulation, verbose, storagegroups, ffmpeg, channel_id, channel_num
      global flat, download_sleeptime, channel_watch_only, channel_mythvideo_only, channel_new_watch_copy
      global vid_graphics_dirs, imagemagick, statistics, requirements_are_met
      global graphic_suffix, graphic_path_suffix, graphic_name_suffix
      global mythcommflag_recordings, mythcommflag_videos
      global local_only, metadata
      global parser, opts, args
  
      if opts.examples:                    # Display example information
          sys.stdout.write(examples_txt+'\n')
          sys.exit(0)
  
      if opts.version:        # Display program information
          sys.stdout.write(u"\nTitle: (%s); Version: description(%s); Author: (%s)\n%s\n" % (
          __title__, __version__, __author__, __purpose__ ))
          sys.exit(0)
  
      if opts.testenv:
          test_environment = True
      else:
          test_environment = False
  
      # Verify that Miro is not currently running
      if isMiroRunning():
          sys.exit(1)
  
      # Verify that only None or one of the mutually exclusive (-W), (-M) and (-N) options is being used
      x = 0
      if opts.new_watch_copy: x+=1
      if opts.watch_only: x+=1
      if opts.mythvideo_only: x+=1
      if opts.import_opml: x+=1
      if x > 1:
          logger.critical(u"The (-W), (-M), (-N) and (-i) options are mutually exclusive, "\
                          u"so only one can be specified at a time.")
          sys.exit(1)
  
      # Set option related global variables
      simulation = opts.simulation
      verbose = opts.verbose
      if opts.hostname:    # Override localhostname if the user specified an hostname
          localhostname = opts.hostname
  
      # Validate settings
  
      ## Video base directory and current version and revision numbers
      base_video_dir = miroConfiguration(prefs.MOVIES_DIRECTORY)
      miro_version_rev = u"%s r%s" % (miroConfiguration(prefs.APP_VERSION),
                                      miroConfiguration(prefs.APP_REVISION_NUM))
  
      displayMessage(u"Miro Version (%s)" % (miro_version_rev))
      displayMessage(u"Base Miro Video Directory (%s)" % (base_video_dir,))
      logger.info(u'')
  
      # Verify Miro version sufficent and Video file configuration correct.
      if not os.path.isdir(base_video_dir):
          logger.critical(u"The Miro Videos directory (%s) does not exist." % str(base_video_dir))
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      if miroConfiguration(prefs.APP_VERSION) < u"2.0.3":
          logger.critical((u"The installed version of Miro (%s) is too old. It must be at least "\
                           u"v2.0.3 or higher.") % miroConfiguration(prefs.APP_VERSION))
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      # Miro 4.0.1 has a critical bug that effects MiroBridge. Miro must be upgraded.
      if miroConfiguration(prefs.APP_VERSION) == u"4.0.1":
          logger.critical((u"The installed version of Miro (%s) must be upgraded to Miro version "\
                           u"4.0.2 or higher.") % miroConfiguration(prefs.APP_VERSION))
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      # Verify that the import opml option can be used
      if opts.import_opml:
          if miroConfiguration(prefs.APP_VERSION) < u"2.5.2":
              logger.critical(u"The OPML import option requires Miro v2.5.2 or higher your Miro "\
                              u"(%s) is too old." % miroConfiguration(prefs.APP_VERSION))
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
          if not os.path.isfile(opts.import_opml):
              logger.critical(u"The OPML import file (%s) does not exist" % opts.import_opml)
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
          if len(opts.import_opml) > 5:
              if not opts.import_opml[:-4] != '.opml':
                  logger.critical(u"The OPML import file (%s) must had a file extention of '.opml'" % \
                                          opts.import_opml)
                  if test_environment:
                      requirements_are_met = False
                  else:
                      sys.exit(1)
          else:
              logger.critical(u"The OPML import file (%s) must had a file extention of '.opml'" % \
                                          opts.import_opml)
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
  
      # Get storage groups
      if getStorageGroups() == False:
          logger.critical(u"Retrieving storage groups from the MythTV data base failed")
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
      elif not u'default' in storagegroups.keys():
          logger.critical(u"There must be a 'Default' storage group")
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      if opts.channel:
          channel = opts.channel.split(u':')
          if len(channel) != 2:
              logger.critical((u"The Channel (%s) must be in the format xxx:yyy with x and "\
                               u"y all numeric.") % str(opts.channel))
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
          elif not _can_int(channel[0]) or  not _can_int(channel[1]):
              logger.critical(u"The Channel_id (%s) and Channel_num (%s) must be numeric." % \
                                      (channel[0], channel[1]))
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
          else:
              channel_id = int(channel[0])
              channel_num = int(channel[1])
  
      if opts.sleeptime:
          if not _can_int(opts.sleeptime):
              logger.critical(u"Auto-download sleep time (%s) must be numeric." % str(opts.sleeptime))
              if test_environment:
                  requirements_are_met = False
              else:
                  sys.exit(1)
          else:
              download_sleeptime = float(opts.sleeptime)
  
      getMythtvDirectories()    # Initialize all the Video and graphics directory dictionary
  
      if opts.nosubdirs: # Did the user want a flat MythVideo "Miro" directory structure?
          flat = True
  
      # Get the values in the mirobridge.conf configuration file
      setUseroptions()
  
      if opts.watch_only:
          # ALL Miro videos will only be viewed in the MythTV "Watch Recordings" screen
          channel_watch_only = [u'all']
  
      if opts.mythvideo_only: # ALL Miro videos will be copied to MythVideo and removed from Miro
          channel_mythvideo_only = {u'all': vid_graphics_dirs[u'mythvideo']+u'Miro/'}
  
      # Once watched ALL Miro videos will be copied to MythVideo and removed from Miro
      if opts.new_watch_copy:
          channel_new_watch_copy = {u'all': vid_graphics_dirs[u'mythvideo']+u'Miro/'}
  
      # Verify that "Mythvideo Only" and "New-Watch-Copy" channels do not clash
      if len(channel_mythvideo_only) and len(channel_new_watch_copy):
          for key in channel_mythvideo_only.keys():
              if key in channel_new_watch_copy.keys():
                  logger.critical((u'The Miro Channel (%s) cannot be used as both a "Mythvideo '\
                                   u'Only" and "New-Watch-Copy" channel.') % key)
                  if test_environment:
                      requirements_are_met = False
                  else:
                      sys.exit(1)
  
      # Verify that ImageMagick is installed
      ret = useImageMagick(u"convert -version")
      if ret < 0 or ret > 1:
          logger.critical(u"ImageMagick must be installed, graphics cannot be resized or "\
                          u"converted to the required graphics format (e.g. jpg and or png)")
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      # Verify that the "DeletesFollowLinks" setting is not set to the character '1'
      if mythdb.settings.NULL.DeletesFollowLinks == '1':
          logger.critical(u'The MythTV back end setting "Follow symbolic links when deleting '\
                          u'files" is checked and it is incompatible with MiroBridge processing. '\
                          u'It must be unchecked it to use MiroBridge.\nTo uncheck this setting '\
                          u'start "mythtv-setup" or with Mythbuntu start "MythTV Backend Setup" '\
                          u'and then General->Miscellaneous Settings and uncheck the "Follow '\
                          u'symbolic links when deleting files" setting')
          if test_environment:
              requirements_are_met = False
          else:
              sys.exit(1)
  
      # Initialize class with the metadata methods
      metadata = MetaData(mythdb,
                  Video,
                  Record,
                  storagegroups,
                  vid_graphics_dirs,
                  channel_id,
                  ffmpeg,
                  logger,
                  simulation,
                  verbose,
                  )
  
      if opts.testenv:        # All tests passed
          metadata.getVideoDetails(u"") # Test that ffmpeg is available
          if ffmpeg and requirements_are_met:
              logger.info(u"The environment test passed !\n\n")
              sys.exit(0)
          else:
              logger.critical(u"The environment test FAILED. See previously displayed error messages!")
              sys.exit(1)
  
      if opts.addchannel != u'OFF':    # Add a Miro Channel record - Should only be done once
          createChannelRecord(opts.addchannel, channel_id, channel_num)
          logger.info(u"The Miro Channel record has been successfully created !\n\n")
          sys.exit(0)
  
  
      ###########################################
      # Mainlogic for all Miro bridge and MythTV
      ###########################################
  
      #
      # Start the Miro Front and Backend - This allows mirobridge to execute actions on the Miro backend
      #
      displayMessage(u"Starting Miro Frontend and Backend")
      startup.initialize(miroConfiguration(prefs.THEME_NAME))
      #
      # Only required for Miro 4
      if miroConfiguration(prefs.APP_VERSION)[0] == u"4":
          app.info_updater = InfoUpdater()
      app.cli_events = EventHandler()
      app.cli_events.connect_to_signals()
  
      # Only required for Miro 4 and higher
      if miroConfiguration(prefs.APP_VERSION) > u"4.0":
          startup.install_first_time_handler(app.cli_events.handle_first_time)
  
      startup.startup()
      app.cli_events.startup_event.wait()
      if app.cli_events.startup_failure:
          logger.critical(
  u"Starting Miro Frontend and Backend failed: (%s)\n(%s)" % \
              (app.cli_events.startup_failure[0],
              app.cli_events.startup_failure[1]))
          app.controller.shutdown()
          time.sleep(5) # Let the shutdown processing complete
          sys.exit(1)
  
      # Only required for Miro 4
      if miroConfiguration(prefs.APP_VERSION)[0] == u"4":
          app.movie_data_program_info = movie_data_program_info
      # Only required for Miro 4 and higher
      if miroConfiguration(prefs.APP_VERSION) > u"4.0":
          messages.FrontendStarted().send_to_backend()
  
      app.cli_interpreter = MiroInterpreter()
      if opts.verbose:
          app.cli_interpreter.verbose = True
      else:
          app.cli_interpreter.verbose = False
      app.cli_interpreter.simulation = opts.simulation
      app.cli_interpreter.videofiles = []
      app.cli_interpreter.downloading = False
      app.cli_interpreter.icon_cache_dir = miroConfiguration(
                                                  prefs.ICON_CACHE_DIRECTORY)
      app.cli_interpreter.imagemagick = imagemagick
      app.cli_interpreter.statistics = statistics
      #
      ## Version specific logic
      if miroConfiguration(prefs.APP_VERSION) < u"2.5.0":
          app.renderer = app.cli_interpreter
      elif miroConfiguration(prefs.APP_VERSION) > u"4.0":
          pass
      else:
          app.movie_data_program_info = \
                                 app.cli_interpreter.movie_data_program_info
  
      #
      # Attempt to import an opml file
      #
      if opts.import_opml:
          results = 0
          try:
              app.cli_interpreter.do_mythtv_import_opml(opts.import_opml)
              # Let the Miro backend process the OPML file before shutting down
              time.sleep(30)
          except Exception, e:
              logger.critical(u"Import of OPML file (%s) failed, error(%s)." %
                                      (opts.import_opml, e))
              results = 1
          # Gracefully close the Miro database and shutdown the Miro Front and Back ends
          app.controller.shutdown()
          time.sleep(5) # Let the shutdown processing complete
          sys.exit(results)
  
      #
      # Optionally Update Miro feeds and
      # download any "autodownloadable" videos which are pending
      #
      if not opts.no_autodownload:
          if opts.verbose:
              app.cli_interpreter.verbose = False
          app.cli_interpreter.do_mythtv_getunwatched(u'')
          before_download = len(app.cli_interpreter.videofiles)
          if opts.verbose:
              app.cli_interpreter.verbose = True
          if miroConfiguration(prefs.APP_VERSION) < u"4.0":
              # Miro 4 automatically refreshes feeds and downloads
              app.cli_interpreter.do_mythtv_update_autodownload(u'')
          time.sleep(download_sleeptime)
          firsttime = True
          while True:
              app.cli_interpreter.do_mythtv_check_downloading(u'')
              if app.cli_interpreter.downloading:
                  time.sleep(30)
                  firsttime = False
                  continue
              elif firsttime:
                  time.sleep(download_sleeptime)
                  firsttime = False
                  continue
              else:
                  break
          if opts.verbose:
              app.cli_interpreter.verbose = False
          app.cli_interpreter.do_mythtv_getunwatched(u'')
          after_download = len(app.cli_interpreter.videofiles)
          statistics[u'Miros_videos_downloaded'] = after_download - before_download
          if opts.verbose:
              app.cli_interpreter.verbose = True
  
      # Deal with orphaned oldrecorded records.
      # These records indicate that the MythTV user deleted the video
      # from the Watched Recordings screen or from MythVideo
      # These video items must also be deleted from Miro
      videostodelete = getOldrecordedOrphans()
      if len(videostodelete):
          displayMessage(
              u"Starting Miro delete of videos deleted in the MythTV "\
                         u"Watched Recordings screen.")
          for video in videostodelete:
              # Completely remove the video and item information from Miro
              app.cli_interpreter.do_mythtv_item_remove(
                              [video[u'title'], video[u'subtitle']])
  
      #
      # Collect the set of played Miro video files
      #
      app.cli_interpreter.videofiles = getPlayedMiroVideos()
      #
      # Updated the played status of items
      #
      if app.cli_interpreter.videofiles:
          displayMessage(u"Starting Miro update of watched MythTV videos")
          app.cli_interpreter.do_mythtv_updatewatched(u'')
  
      #
      # Get the unwatched videos details from Miro
      #
      app.cli_interpreter.do_mythtv_getunwatched(u'')
      unwatched = app.cli_interpreter.videofiles
      #
      # Get the watched videos details from Miro
      #
      app.cli_interpreter.do_mythtv_getwatched(u'')
      watched = app.cli_interpreter.videofiles
      #
      # Massage empty titles and subtitles from Miro
      #
      for item in unwatched:
          # Deal with empty titles and subtitles from Miro
          if not item[u'channelTitle']:
              item[u'channelTitle'] = emptyTitle
          if not item[u'title']:
              item[u'title'] = emptySubTitle
      for item in watched:
          # Deal with empty titles and subtitles from Miro
          if not item[u'channelTitle']:
              item[u'channelTitle'] = emptyTitle
          if not item[u'title']:
              item[u'title'] = emptySubTitle
  
      #
      # Remove any duplicate Miro videoes from the unwatched or watched list of Miro videos
      # This means that Miro has duplicates due to a Miro/Channel website issue
      # These videos should not be added to the MythTV Watch Recordings screen
      #
      unwatched_copy = []
      for item in unwatched:
          unwatched_copy.append(item)
      for item in unwatched_copy: # Check for a duplicate against already watched Miro videos
          for x in watched:
              if item[u'channelTitle'] == x[u'channelTitle'] and \
                                          item[u'title'] == x[u'title']:
                  try:
                      unwatched.remove(item)
                      # Completely remove this duplicate video and item information from Miro
                      app.cli_interpreter.do_mythtv_item_remove(
                                                  item[u'videoFilename'])
                      displayMessage((
  u'''Skipped adding a duplicate Miro video to the MythTV
  Watch Recordings screen (%s - %s) which is already in
  MythVideo.
  Sometimes a Miro channel has the same video
  downloaded multiple times.
  This is a Miro/Channel web site issue and often
  rectifies itself overtime.''') % (item[u'channelTitle'], item[u'title']))
                  except ValueError:
                      pass
      duplicates = []
      for item in unwatched_copy:
          dup_flag = 0
          for x in unwatched: # Check for a duplicate against un-watched Miro videos
              if item[u'channelTitle'] == x[u'channelTitle'] and item[u'title'] == x[u'title']:
                  dup_flag+=1
          if dup_flag > 1:
              for x in duplicates:
                  if item[u'channelTitle'] == x[u'channelTitle'] and item[u'title'] == x[u'title']:
                      break
              else:
                  duplicates.append(item)
  
      for duplicate in duplicates:
          try:
              unwatched.remove(duplicate)
              # Completely remove this duplicate video and item information from Miro
              app.cli_interpreter.do_mythtv_item_remove(duplicate[u'videoFilename'])
              displayMessage((u"Skipped adding a Miro video to the MythTV Watch Recordings "\
                              u"screen (%s - %s) as there are duplicate 'new' video items."\
                              u"\nSometimes a Miro channel has the same video downloaded "\
                              u"multiple times.\nThis is a Miro/Channel web site issue and "\
                              u"often rectifies itself overtime.") % \
                                      (duplicate[u'channelTitle'], duplicate[u'title']))
          except ValueError:
              pass
  
      #
      # Deal with any Channel videos that are to be copied and removed from Miro
      #
      copy_items = []
      # Copy unwatched and watched Miro videos (all or only selected Channels)
      if u'all' in channel_mythvideo_only.keys():
          for array in [watched, unwatched]:
              for item in array:
                  copy_items.append(item)
      elif len(channel_mythvideo_only):
          for array in [watched, unwatched]:
              for video in array:
                  if filter(is_not_punct_char, video[u'channelTitle'].lower()) in \
                              channel_mythvideo_only.keys():
                      copy_items.append(video)
      # Copy ONLY watched Miro videos (all or only selected Channels)
      if u'all' in channel_new_watch_copy.keys():
          for video in watched:
              copy_items.append(video)
      elif len(channel_new_watch_copy):
          for video in watched:
              if filter(is_not_punct_char, video[u'channelTitle'].lower()) in \
                              channel_new_watch_copy.keys():
                  copy_items.append(video)
  
      channels_to_copy = {}
      for key in channel_mythvideo_only.keys():
          channels_to_copy[key] = channel_mythvideo_only[key]
      for key in channel_new_watch_copy.keys():
          channels_to_copy[key] = channel_new_watch_copy[key]
  
      for video in copy_items:
          if channels_to_copy.has_key('all'):
              copy_dir = u"%s%s/" % (channels_to_copy['all'], sanitiseFileName(video[u'channelTitle']))
          else:
              copy_dir = channels_to_copy[filter(is_not_punct_char, video[u'channelTitle'].lower())]
  
          # Create the subdirectories to copy the video into
          if not os.path.isdir(copy_dir):
              if simulation:
                  logger.info(u"Simulation: Creating the MythVideo directory (%s)." % (copy_dir))
              else:
                  os.makedirs(copy_dir)
  
          # Copy the Miro video file
          # This filename is needed later for deleting in Miro
          save_video_filename = video[u'videoFilename']
          ext = getExtention(video[u'videoFilename'])
          if ext.lower() == u'm4v':
              ext = u'mpg'
          filepath = u"%s%s - %s.%s" % (copy_dir, sanitiseFileName(video[u'channelTitle']),
                                        sanitiseFileName(video[u'title']), ext)
          if simulation:
              logger.info(u"Simulation: Copying the Miro video (%s) to the MythVideo directory (%s)." % \
                                  (video[u'videoFilename'], filepath))
          else:
              try:    # Miro video copied into a MythVideo directory
                  shutil.copy2(video[u'videoFilename'], filepath)
                  statistics[u'Miros_MythVideos_copied']+=1
                  if u'mythvideo' in storagegroups.keys() and not local_only:
                      video[u'videoFilename'] = filepath.replace(storagegroups[u'mythvideo'], u'')
                  else:
                      video[u'videoFilename'] = filepath
              except Exception, e:
                  logger.critical((u"Copying the Miro video (%s) to the MythVideo directory (%s)."\
                                   u"\n         This maybe a permissions error (mirobridge.py does "\
                                   u"not have permission to write to the directory), error(%s)") % \
                                              (video[u'videoFilename'], filepath, e))
                  # Gracefully close the Miro database and shutdown the Miro Front and Back ends
                  app.controller.shutdown()
                  time.sleep(5) # Let the shutdown processing complete
                  sys.exit(1)
  
          # Copy the Channel or item's icon
          if video[u'channel_icon'] and not video[u'channelTitle'].lower() in channel_icon_override:
              pass
          else:
              if video[u'item_icon']:
                  video[u'channel_icon'] = video[u'item_icon']
          # Get any graphics that already exist
          graphics = metadata.getMetadata(sanitiseFileName(video[u'channelTitle']))
          if video[u'channel_icon'] and graphics['coverart'] == u'':
              ext = getExtention(video[u'channel_icon'])
              if video[u'channelTitle'].lower() in channel_icon_override:
                  filepath = u"%s%s - %s%s.%s" % (vid_graphics_dirs[u'posterdir'],
                                                  sanitiseFileName(video[u'channelTitle']),
                                                  sanitiseFileName(video[u'title']),
                                                  graphic_suffix[u'posterdir'], ext)
              else:
                  filepath = u"%s%s%s.%s" % (vid_graphics_dirs[u'posterdir'],
                                             sanitiseFileName(video[u'channelTitle']),
                                             graphic_suffix[u'posterdir'], ext)
              # There may already be a Channel icon available
              # or it is a symlink which needs to be replaced
              if not os.path.isfile(filepath) or os.path.islink(filepath):
                  if simulation:
                      logger.info((u"Simulation: Copying the Channel Icon (%s) to the poster "\
                                   u"directory (%s).") % (video[u'channel_icon'], filepath))
                  else:
                      try:    # Miro Channel icon copied into a MythVideo directory
                          try: # Remove any old symlink file
                              os.remove(filepath)
                          except OSError:
                              pass
                          shutil.copy2(video[u'channel_icon'], filepath)
                          if u'posterdir' in storagegroups.keys() and not local_only:
                              video[u'channel_icon'] = filepath.replace(storagegroups[u'posterdir'], u'')
                          else:
                              video[u'channel_icon'] = filepath
                      except Exception, e:
                          logger.critical((u"Copying the Channel Icon (%s) to the poster directory "\
                                           u"(%s).\n         This maybe a permissions error "\
                                           u"(mirobridge.py does not have permission to write to the "\
                                           u"directory), error(%s)") % \
                                      (video[u'channel_icon'], filepath, e))
                          # Gracefully close the Miro database and shutdown the Miro Front and Back ends
                          app.controller.shutdown()
                          time.sleep(5) # Let the shutdown processing complete
                          sys.exit(1)
              else:
                  if u'posterdir' in storagegroups.keys() and not local_only:
                      video[u'channel_icon'] = filepath.replace(storagegroups[u'posterdir'], u'')
                  else:
                      video[u'channel_icon'] = filepath
          else:
              video[u'channel_icon'] = graphics['coverart']
  
          # There may already be a Screenshot available or it is a symlink which needs to be replaced
          if video[u'screenshot']:
              ext = getExtention(video[u'screenshot'])
              filepath = u"%s%s - %s%s.%s" % (vid_graphics_dirs[u'episodeimagedir'],
                                              sanitiseFileName(video[u'channelTitle']),
                                              sanitiseFileName(video[u'title']),
                                              graphic_suffix[u'episodeimagedir'], ext)
          else:
              filepath = u''
  
          if not os.path.isfile(filepath) or os.path.islink(filepath):
              if video[u'screenshot']:
                  if simulation:
                      logger.info((u"Simulation: Copying the Screenshot (%s) to the Screenshot "\
                                   u"directory (%s).") % (video[u'screenshot'], filepath))
                  else:
                      try:    # Miro Channel icon copied into a MythVideo directory
                          try: # Remove any old symlink file
                              os.remove(filepath)
                          except OSError:
                              pass
                          shutil.copy2(video[u'screenshot'], filepath)
                          displayMessage(u"Copied Miro screenshot file (%s) to MythVideo (%s)" % \
                                                  (video[u'screenshot'], filepath))
                          if u'episodeimagedir' in storagegroups.keys() and not local_only:
                              video[u'screenshot'] = filepath.replace(storagegroups[u'episodeimagedir'],
                                                                      u'')
                          else:
                              video[u'screenshot'] = filepath
                      except Exception, e:
                          logger.critical((u"Copying the Screenshot (%s) to the Screenshot directory "\
                                           u"(%s).\n         This maybe a permissions error "\
                                           u"(mirobridge.py does not have permission to write to the "\
                                           u"directory), error(%s)") % \
                                  (video[u'screenshot'], filepath, e))
                          # Gracefully close the Miro database and shutdown the Miro Front and Back ends
                          app.controller.shutdown()
                          time.sleep(5) # Let the shutdown processing complete
                          sys.exit(1)
          elif video[u'screenshot']:
              if u'episodeimagedir' in storagegroups.keys() and not local_only:
                  video[u'screenshot'] = filepath.replace(storagegroups[u'episodeimagedir'], u'')
              else:
                  video[u'screenshot'] = filepath
          video[u'copied'] = True     # Mark this video item as being copied
  
          # Completely remove the video and item information from Miro
          app.cli_interpreter.do_mythtv_item_remove(save_video_filename)
  
  
      # Gracefully close the Miro database and shutdown the Miro Front and Back ends
      app.controller.shutdown()
      time.sleep(5) # Let the shutdown processing complete
  
      #
      # Add and delete MythTV (Watch Recordings) Miro recorded records
      # Add and remove symlinks for Miro video files
      #
  
      # Check if the user does not want any channels Added to the "Watch Recordings" screen
      if channel_mythvideo_only.has_key(u'all'):
          for video in unwatched:
              watched.append(video)
          unwatched = []
      else:
          if len(channel_mythvideo_only):
              unwatched_copy = []
              for video in unwatched:
                  if not filter(is_not_punct_char, video[u'channelTitle'].lower()) in \
                              channel_mythvideo_only.keys():
                      unwatched_copy.append(video)
                  else:
                      watched.append(video)
              unwatched = unwatched_copy
  
      statistics[u'Total_unwatched'] = len(unwatched)
      if not len(unwatched):
          displayMessage(u"There are no Miro unwatched video items to add as MythTV Recorded videos.")
      if not updateMythRecorded(unwatched):
          logger.critical(u"Updating MythTV Recording with Miro video files failed." % \
                                      str(base_video_dir))
          sys.exit(1)
  
      #
      # Add and delete MythVideo records for played Miro Videos
      # Add and delete symbolic links to Miro Videos and subdirectories
      # Add and delete symbolic links to coverart/Miro icons and Miro screenshots/fanart
      #
      if len(channel_watch_only): # If the user does not want any channels moved to MythVideo exit
          if channel_watch_only[0].lower() == u'all':
              printStatistics()
              return True
  
      if not len(watched):
          displayMessage(u"There are no Miro watched items to add to MythVideo")
      if not updateMythVideo(watched):
          logger.critical(u"Updating MythVideo with Miro video files failed.")
          sys.exit(1)
  
      printStatistics()
      return True
function_tokens: def main ( ) : global localhostname , simulation , verbose , storagegroups , ffmpeg , channel_id , channel_num global flat , download_sleeptime , channel_watch_only , channel_mythvideo_only , channel_new_watch_copy global vid_graphics_dirs , imagemagick , statistics , requirements_are_met global graphic_suffix , graphic_path_suffix , graphic_name_suffix global mythcommflag_recordings , mythcommflag_videos global local_only , metadata global parser , opts , args if opts . examples : # Display example information sys . stdout . write ( examples_txt + '\n' ) sys . exit ( 0 ) if opts . version : # Display program information sys . stdout . write ( u"\nTitle: (%s); Version: description(%s); Author: (%s)\n%s\n" % ( __title__ , __version__ , __author__ , __purpose__ ) ) sys . exit ( 0 ) if opts . testenv : test_environment = True else : test_environment = False # Verify that Miro is not currently running if isMiroRunning ( ) : sys . exit ( 1 ) # Verify that only None or one of the mutually exclusive (-W), (-M) and (-N) options is being used x = 0 if opts . new_watch_copy : x += 1 if opts . watch_only : x += 1 if opts . mythvideo_only : x += 1 if opts . import_opml : x += 1 if x > 1 : logger . critical ( u"The (-W), (-M), (-N) and (-i) options are mutually exclusive, " u"so only one can be specified at a time." ) sys . exit ( 1 ) # Set option related global variables simulation = opts . simulation verbose = opts . verbose if opts . hostname : # Override localhostname if the user specified an hostname localhostname = opts . hostname # Validate settings ## Video base directory and current version and revision numbers base_video_dir = miroConfiguration ( prefs . MOVIES_DIRECTORY ) miro_version_rev = u"%s r%s" % ( miroConfiguration ( prefs . APP_VERSION ) , miroConfiguration ( prefs . APP_REVISION_NUM ) ) displayMessage ( u"Miro Version (%s)" % ( miro_version_rev ) ) displayMessage ( u"Base Miro Video Directory (%s)" % ( base_video_dir , ) ) logger . info ( u'' ) # Verify Miro version sufficent and Video file configuration correct. if not os . path . isdir ( base_video_dir ) : logger . critical ( u"The Miro Videos directory (%s) does not exist." % str ( base_video_dir ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) if miroConfiguration ( prefs . APP_VERSION ) < u"2.0.3" : logger . critical ( ( u"The installed version of Miro (%s) is too old. It must be at least " u"v2.0.3 or higher." ) % miroConfiguration ( prefs . APP_VERSION ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Miro 4.0.1 has a critical bug that effects MiroBridge. Miro must be upgraded. if miroConfiguration ( prefs . APP_VERSION ) == u"4.0.1" : logger . critical ( ( u"The installed version of Miro (%s) must be upgraded to Miro version " u"4.0.2 or higher." ) % miroConfiguration ( prefs . APP_VERSION ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Verify that the import opml option can be used if opts . import_opml : if miroConfiguration ( prefs . APP_VERSION ) < u"2.5.2" : logger . critical ( u"The OPML import option requires Miro v2.5.2 or higher your Miro " u"(%s) is too old." % miroConfiguration ( prefs . APP_VERSION ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) if not os . path . isfile ( opts . import_opml ) : logger . critical ( u"The OPML import file (%s) does not exist" % opts . import_opml ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) if len ( opts . import_opml ) > 5 : if not opts . import_opml [ : - 4 ] != '.opml' : logger . critical ( u"The OPML import file (%s) must had a file extention of '.opml'" % opts . import_opml ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) else : logger . critical ( u"The OPML import file (%s) must had a file extention of '.opml'" % opts . import_opml ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Get storage groups if getStorageGroups ( ) == False : logger . critical ( u"Retrieving storage groups from the MythTV data base failed" ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) elif not u'default' in storagegroups . keys ( ) : logger . critical ( u"There must be a 'Default' storage group" ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) if opts . channel : channel = opts . channel . split ( u':' ) if len ( channel ) != 2 : logger . critical ( ( u"The Channel (%s) must be in the format xxx:yyy with x and " u"y all numeric." ) % str ( opts . channel ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) elif not _can_int ( channel [ 0 ] ) or not _can_int ( channel [ 1 ] ) : logger . critical ( u"The Channel_id (%s) and Channel_num (%s) must be numeric." % ( channel [ 0 ] , channel [ 1 ] ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) else : channel_id = int ( channel [ 0 ] ) channel_num = int ( channel [ 1 ] ) if opts . sleeptime : if not _can_int ( opts . sleeptime ) : logger . critical ( u"Auto-download sleep time (%s) must be numeric." % str ( opts . sleeptime ) ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) else : download_sleeptime = float ( opts . sleeptime ) getMythtvDirectories ( ) # Initialize all the Video and graphics directory dictionary if opts . nosubdirs : # Did the user want a flat MythVideo "Miro" directory structure? flat = True # Get the values in the mirobridge.conf configuration file setUseroptions ( ) if opts . watch_only : # ALL Miro videos will only be viewed in the MythTV "Watch Recordings" screen channel_watch_only = [ u'all' ] if opts . mythvideo_only : # ALL Miro videos will be copied to MythVideo and removed from Miro channel_mythvideo_only = { u'all' : vid_graphics_dirs [ u'mythvideo' ] + u'Miro/' } # Once watched ALL Miro videos will be copied to MythVideo and removed from Miro if opts . new_watch_copy : channel_new_watch_copy = { u'all' : vid_graphics_dirs [ u'mythvideo' ] + u'Miro/' } # Verify that "Mythvideo Only" and "New-Watch-Copy" channels do not clash if len ( channel_mythvideo_only ) and len ( channel_new_watch_copy ) : for key in channel_mythvideo_only . keys ( ) : if key in channel_new_watch_copy . keys ( ) : logger . critical ( ( u'The Miro Channel (%s) cannot be used as both a "Mythvideo ' u'Only" and "New-Watch-Copy" channel.' ) % key ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Verify that ImageMagick is installed ret = useImageMagick ( u"convert -version" ) if ret < 0 or ret > 1 : logger . critical ( u"ImageMagick must be installed, graphics cannot be resized or " u"converted to the required graphics format (e.g. jpg and or png)" ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Verify that the "DeletesFollowLinks" setting is not set to the character '1' if mythdb . settings . NULL . DeletesFollowLinks == '1' : logger . critical ( u'The MythTV back end setting "Follow symbolic links when deleting ' u'files" is checked and it is incompatible with MiroBridge processing. ' u'It must be unchecked it to use MiroBridge.\nTo uncheck this setting ' u'start "mythtv-setup" or with Mythbuntu start "MythTV Backend Setup" ' u'and then General->Miscellaneous Settings and uncheck the "Follow ' u'symbolic links when deleting files" setting' ) if test_environment : requirements_are_met = False else : sys . exit ( 1 ) # Initialize class with the metadata methods metadata = MetaData ( mythdb , Video , Record , storagegroups , vid_graphics_dirs , channel_id , ffmpeg , logger , simulation , verbose , ) if opts . testenv : # All tests passed metadata . getVideoDetails ( u"" ) # Test that ffmpeg is available if ffmpeg and requirements_are_met : logger . info ( u"The environment test passed !\n\n" ) sys . exit ( 0 ) else : logger . critical ( u"The environment test FAILED. See previously displayed error messages!" ) sys . exit ( 1 ) if opts . addchannel != u'OFF' : # Add a Miro Channel record - Should only be done once createChannelRecord ( opts . addchannel , channel_id , channel_num ) logger . info ( u"The Miro Channel record has been successfully created !\n\n" ) sys . exit ( 0 ) ########################################### # Mainlogic for all Miro bridge and MythTV ########################################### # # Start the Miro Front and Backend - This allows mirobridge to execute actions on the Miro backend # displayMessage ( u"Starting Miro Frontend and Backend" ) startup . initialize ( miroConfiguration ( prefs . THEME_NAME ) ) # # Only required for Miro 4 if miroConfiguration ( prefs . APP_VERSION ) [ 0 ] == u"4" : app . info_updater = InfoUpdater ( ) app . cli_events = EventHandler ( ) app . cli_events . connect_to_signals ( ) # Only required for Miro 4 and higher if miroConfiguration ( prefs . APP_VERSION ) > u"4.0" : startup . install_first_time_handler ( app . cli_events . handle_first_time ) startup . startup ( ) app . cli_events . startup_event . wait ( ) if app . cli_events . startup_failure : logger . critical ( u"Starting Miro Frontend and Backend failed: (%s)\n(%s)" % ( app . cli_events . startup_failure [ 0 ] , app . cli_events . startup_failure [ 1 ] ) ) app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete sys . exit ( 1 ) # Only required for Miro 4 if miroConfiguration ( prefs . APP_VERSION ) [ 0 ] == u"4" : app . movie_data_program_info = movie_data_program_info # Only required for Miro 4 and higher if miroConfiguration ( prefs . APP_VERSION ) > u"4.0" : messages . FrontendStarted ( ) . send_to_backend ( ) app . cli_interpreter = MiroInterpreter ( ) if opts . verbose : app . cli_interpreter . verbose = True else : app . cli_interpreter . verbose = False app . cli_interpreter . simulation = opts . simulation app . cli_interpreter . videofiles = [ ] app . cli_interpreter . downloading = False app . cli_interpreter . icon_cache_dir = miroConfiguration ( prefs . ICON_CACHE_DIRECTORY ) app . cli_interpreter . imagemagick = imagemagick app . cli_interpreter . statistics = statistics # ## Version specific logic if miroConfiguration ( prefs . APP_VERSION ) < u"2.5.0" : app . renderer = app . cli_interpreter elif miroConfiguration ( prefs . APP_VERSION ) > u"4.0" : pass else : app . movie_data_program_info = app . cli_interpreter . movie_data_program_info # # Attempt to import an opml file # if opts . import_opml : results = 0 try : app . cli_interpreter . do_mythtv_import_opml ( opts . import_opml ) # Let the Miro backend process the OPML file before shutting down time . sleep ( 30 ) except Exception , e : logger . critical ( u"Import of OPML file (%s) failed, error(%s)." % ( opts . import_opml , e ) ) results = 1 # Gracefully close the Miro database and shutdown the Miro Front and Back ends app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete sys . exit ( results ) # # Optionally Update Miro feeds and # download any "autodownloadable" videos which are pending # if not opts . no_autodownload : if opts . verbose : app . cli_interpreter . verbose = False app . cli_interpreter . do_mythtv_getunwatched ( u'' ) before_download = len ( app . cli_interpreter . videofiles ) if opts . verbose : app . cli_interpreter . verbose = True if miroConfiguration ( prefs . APP_VERSION ) < u"4.0" : # Miro 4 automatically refreshes feeds and downloads app . cli_interpreter . do_mythtv_update_autodownload ( u'' ) time . sleep ( download_sleeptime ) firsttime = True while True : app . cli_interpreter . do_mythtv_check_downloading ( u'' ) if app . cli_interpreter . downloading : time . sleep ( 30 ) firsttime = False continue elif firsttime : time . sleep ( download_sleeptime ) firsttime = False continue else : break if opts . verbose : app . cli_interpreter . verbose = False app . cli_interpreter . do_mythtv_getunwatched ( u'' ) after_download = len ( app . cli_interpreter . videofiles ) statistics [ u'Miros_videos_downloaded' ] = after_download - before_download if opts . verbose : app . cli_interpreter . verbose = True # Deal with orphaned oldrecorded records. # These records indicate that the MythTV user deleted the video # from the Watched Recordings screen or from MythVideo # These video items must also be deleted from Miro videostodelete = getOldrecordedOrphans ( ) if len ( videostodelete ) : displayMessage ( u"Starting Miro delete of videos deleted in the MythTV " u"Watched Recordings screen." ) for video in videostodelete : # Completely remove the video and item information from Miro app . cli_interpreter . do_mythtv_item_remove ( [ video [ u'title' ] , video [ u'subtitle' ] ] ) # # Collect the set of played Miro video files # app . cli_interpreter . videofiles = getPlayedMiroVideos ( ) # # Updated the played status of items # if app . cli_interpreter . videofiles : displayMessage ( u"Starting Miro update of watched MythTV videos" ) app . cli_interpreter . do_mythtv_updatewatched ( u'' ) # # Get the unwatched videos details from Miro # app . cli_interpreter . do_mythtv_getunwatched ( u'' ) unwatched = app . cli_interpreter . videofiles # # Get the watched videos details from Miro # app . cli_interpreter . do_mythtv_getwatched ( u'' ) watched = app . cli_interpreter . videofiles # # Massage empty titles and subtitles from Miro # for item in unwatched : # Deal with empty titles and subtitles from Miro if not item [ u'channelTitle' ] : item [ u'channelTitle' ] = emptyTitle if not item [ u'title' ] : item [ u'title' ] = emptySubTitle for item in watched : # Deal with empty titles and subtitles from Miro if not item [ u'channelTitle' ] : item [ u'channelTitle' ] = emptyTitle if not item [ u'title' ] : item [ u'title' ] = emptySubTitle # # Remove any duplicate Miro videoes from the unwatched or watched list of Miro videos # This means that Miro has duplicates due to a Miro/Channel website issue # These videos should not be added to the MythTV Watch Recordings screen # unwatched_copy = [ ] for item in unwatched : unwatched_copy . append ( item ) for item in unwatched_copy : # Check for a duplicate against already watched Miro videos for x in watched : if item [ u'channelTitle' ] == x [ u'channelTitle' ] and item [ u'title' ] == x [ u'title' ] : try : unwatched . remove ( item ) # Completely remove this duplicate video and item information from Miro app . cli_interpreter . do_mythtv_item_remove ( item [ u'videoFilename' ] ) displayMessage ( ( u'''Skipped adding a duplicate Miro video to the MythTV
  Watch Recordings screen (%s - %s) which is already in
  MythVideo.
  Sometimes a Miro channel has the same video
  downloaded multiple times.
  This is a Miro/Channel web site issue and often
  rectifies itself overtime.''' ) % ( item [ u'channelTitle' ] , item [ u'title' ] ) ) except ValueError : pass duplicates = [ ] for item in unwatched_copy : dup_flag = 0 for x in unwatched : # Check for a duplicate against un-watched Miro videos if item [ u'channelTitle' ] == x [ u'channelTitle' ] and item [ u'title' ] == x [ u'title' ] : dup_flag += 1 if dup_flag > 1 : for x in duplicates : if item [ u'channelTitle' ] == x [ u'channelTitle' ] and item [ u'title' ] == x [ u'title' ] : break else : duplicates . append ( item ) for duplicate in duplicates : try : unwatched . remove ( duplicate ) # Completely remove this duplicate video and item information from Miro app . cli_interpreter . do_mythtv_item_remove ( duplicate [ u'videoFilename' ] ) displayMessage ( ( u"Skipped adding a Miro video to the MythTV Watch Recordings " u"screen (%s - %s) as there are duplicate 'new' video items." u"\nSometimes a Miro channel has the same video downloaded " u"multiple times.\nThis is a Miro/Channel web site issue and " u"often rectifies itself overtime." ) % ( duplicate [ u'channelTitle' ] , duplicate [ u'title' ] ) ) except ValueError : pass # # Deal with any Channel videos that are to be copied and removed from Miro # copy_items = [ ] # Copy unwatched and watched Miro videos (all or only selected Channels) if u'all' in channel_mythvideo_only . keys ( ) : for array in [ watched , unwatched ] : for item in array : copy_items . append ( item ) elif len ( channel_mythvideo_only ) : for array in [ watched , unwatched ] : for video in array : if filter ( is_not_punct_char , video [ u'channelTitle' ] . lower ( ) ) in channel_mythvideo_only . keys ( ) : copy_items . append ( video ) # Copy ONLY watched Miro videos (all or only selected Channels) if u'all' in channel_new_watch_copy . keys ( ) : for video in watched : copy_items . append ( video ) elif len ( channel_new_watch_copy ) : for video in watched : if filter ( is_not_punct_char , video [ u'channelTitle' ] . lower ( ) ) in channel_new_watch_copy . keys ( ) : copy_items . append ( video ) channels_to_copy = { } for key in channel_mythvideo_only . keys ( ) : channels_to_copy [ key ] = channel_mythvideo_only [ key ] for key in channel_new_watch_copy . keys ( ) : channels_to_copy [ key ] = channel_new_watch_copy [ key ] for video in copy_items : if channels_to_copy . has_key ( 'all' ) : copy_dir = u"%s%s/" % ( channels_to_copy [ 'all' ] , sanitiseFileName ( video [ u'channelTitle' ] ) ) else : copy_dir = channels_to_copy [ filter ( is_not_punct_char , video [ u'channelTitle' ] . lower ( ) ) ] # Create the subdirectories to copy the video into if not os . path . isdir ( copy_dir ) : if simulation : logger . info ( u"Simulation: Creating the MythVideo directory (%s)." % ( copy_dir ) ) else : os . makedirs ( copy_dir ) # Copy the Miro video file # This filename is needed later for deleting in Miro save_video_filename = video [ u'videoFilename' ] ext = getExtention ( video [ u'videoFilename' ] ) if ext . lower ( ) == u'm4v' : ext = u'mpg' filepath = u"%s%s - %s.%s" % ( copy_dir , sanitiseFileName ( video [ u'channelTitle' ] ) , sanitiseFileName ( video [ u'title' ] ) , ext ) if simulation : logger . info ( u"Simulation: Copying the Miro video (%s) to the MythVideo directory (%s)." % ( video [ u'videoFilename' ] , filepath ) ) else : try : # Miro video copied into a MythVideo directory shutil . copy2 ( video [ u'videoFilename' ] , filepath ) statistics [ u'Miros_MythVideos_copied' ] += 1 if u'mythvideo' in storagegroups . keys ( ) and not local_only : video [ u'videoFilename' ] = filepath . replace ( storagegroups [ u'mythvideo' ] , u'' ) else : video [ u'videoFilename' ] = filepath except Exception , e : logger . critical ( ( u"Copying the Miro video (%s) to the MythVideo directory (%s)." u"\n         This maybe a permissions error (mirobridge.py does " u"not have permission to write to the directory), error(%s)" ) % ( video [ u'videoFilename' ] , filepath , e ) ) # Gracefully close the Miro database and shutdown the Miro Front and Back ends app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete sys . exit ( 1 ) # Copy the Channel or item's icon if video [ u'channel_icon' ] and not video [ u'channelTitle' ] . lower ( ) in channel_icon_override : pass else : if video [ u'item_icon' ] : video [ u'channel_icon' ] = video [ u'item_icon' ] # Get any graphics that already exist graphics = metadata . getMetadata ( sanitiseFileName ( video [ u'channelTitle' ] ) ) if video [ u'channel_icon' ] and graphics [ 'coverart' ] == u'' : ext = getExtention ( video [ u'channel_icon' ] ) if video [ u'channelTitle' ] . lower ( ) in channel_icon_override : filepath = u"%s%s - %s%s.%s" % ( vid_graphics_dirs [ u'posterdir' ] , sanitiseFileName ( video [ u'channelTitle' ] ) , sanitiseFileName ( video [ u'title' ] ) , graphic_suffix [ u'posterdir' ] , ext ) else : filepath = u"%s%s%s.%s" % ( vid_graphics_dirs [ u'posterdir' ] , sanitiseFileName ( video [ u'channelTitle' ] ) , graphic_suffix [ u'posterdir' ] , ext ) # There may already be a Channel icon available # or it is a symlink which needs to be replaced if not os . path . isfile ( filepath ) or os . path . islink ( filepath ) : if simulation : logger . info ( ( u"Simulation: Copying the Channel Icon (%s) to the poster " u"directory (%s)." ) % ( video [ u'channel_icon' ] , filepath ) ) else : try : # Miro Channel icon copied into a MythVideo directory try : # Remove any old symlink file os . remove ( filepath ) except OSError : pass shutil . copy2 ( video [ u'channel_icon' ] , filepath ) if u'posterdir' in storagegroups . keys ( ) and not local_only : video [ u'channel_icon' ] = filepath . replace ( storagegroups [ u'posterdir' ] , u'' ) else : video [ u'channel_icon' ] = filepath except Exception , e : logger . critical ( ( u"Copying the Channel Icon (%s) to the poster directory " u"(%s).\n         This maybe a permissions error " u"(mirobridge.py does not have permission to write to the " u"directory), error(%s)" ) % ( video [ u'channel_icon' ] , filepath , e ) ) # Gracefully close the Miro database and shutdown the Miro Front and Back ends app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete sys . exit ( 1 ) else : if u'posterdir' in storagegroups . keys ( ) and not local_only : video [ u'channel_icon' ] = filepath . replace ( storagegroups [ u'posterdir' ] , u'' ) else : video [ u'channel_icon' ] = filepath else : video [ u'channel_icon' ] = graphics [ 'coverart' ] # There may already be a Screenshot available or it is a symlink which needs to be replaced if video [ u'screenshot' ] : ext = getExtention ( video [ u'screenshot' ] ) filepath = u"%s%s - %s%s.%s" % ( vid_graphics_dirs [ u'episodeimagedir' ] , sanitiseFileName ( video [ u'channelTitle' ] ) , sanitiseFileName ( video [ u'title' ] ) , graphic_suffix [ u'episodeimagedir' ] , ext ) else : filepath = u'' if not os . path . isfile ( filepath ) or os . path . islink ( filepath ) : if video [ u'screenshot' ] : if simulation : logger . info ( ( u"Simulation: Copying the Screenshot (%s) to the Screenshot " u"directory (%s)." ) % ( video [ u'screenshot' ] , filepath ) ) else : try : # Miro Channel icon copied into a MythVideo directory try : # Remove any old symlink file os . remove ( filepath ) except OSError : pass shutil . copy2 ( video [ u'screenshot' ] , filepath ) displayMessage ( u"Copied Miro screenshot file (%s) to MythVideo (%s)" % ( video [ u'screenshot' ] , filepath ) ) if u'episodeimagedir' in storagegroups . keys ( ) and not local_only : video [ u'screenshot' ] = filepath . replace ( storagegroups [ u'episodeimagedir' ] , u'' ) else : video [ u'screenshot' ] = filepath except Exception , e : logger . critical ( ( u"Copying the Screenshot (%s) to the Screenshot directory " u"(%s).\n         This maybe a permissions error " u"(mirobridge.py does not have permission to write to the " u"directory), error(%s)" ) % ( video [ u'screenshot' ] , filepath , e ) ) # Gracefully close the Miro database and shutdown the Miro Front and Back ends app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete sys . exit ( 1 ) elif video [ u'screenshot' ] : if u'episodeimagedir' in storagegroups . keys ( ) and not local_only : video [ u'screenshot' ] = filepath . replace ( storagegroups [ u'episodeimagedir' ] , u'' ) else : video [ u'screenshot' ] = filepath video [ u'copied' ] = True # Mark this video item as being copied # Completely remove the video and item information from Miro app . cli_interpreter . do_mythtv_item_remove ( save_video_filename ) # Gracefully close the Miro database and shutdown the Miro Front and Back ends app . controller . shutdown ( ) time . sleep ( 5 ) # Let the shutdown processing complete # # Add and delete MythTV (Watch Recordings) Miro recorded records # Add and remove symlinks for Miro video files # # Check if the user does not want any channels Added to the "Watch Recordings" screen if channel_mythvideo_only . has_key ( u'all' ) : for video in unwatched : watched . append ( video ) unwatched = [ ] else : if len ( channel_mythvideo_only ) : unwatched_copy = [ ] for video in unwatched : if not filter ( is_not_punct_char , video [ u'channelTitle' ] . lower ( ) ) in channel_mythvideo_only . keys ( ) : unwatched_copy . append ( video ) else : watched . append ( video ) unwatched = unwatched_copy statistics [ u'Total_unwatched' ] = len ( unwatched ) if not len ( unwatched ) : displayMessage ( u"There are no Miro unwatched video items to add as MythTV Recorded videos." ) if not updateMythRecorded ( unwatched ) : logger . critical ( u"Updating MythTV Recording with Miro video files failed." % str ( base_video_dir ) ) sys . exit ( 1 ) # # Add and delete MythVideo records for played Miro Videos # Add and delete symbolic links to Miro Videos and subdirectories # Add and delete symbolic links to coverart/Miro icons and Miro screenshots/fanart # if len ( channel_watch_only ) : # If the user does not want any channels moved to MythVideo exit if channel_watch_only [ 0 ] . lower ( ) == u'all' : printStatistics ( ) return True if not len ( watched ) : displayMessage ( u"There are no Miro watched items to add to MythVideo" ) if not updateMythVideo ( watched ) : logger . critical ( u"Updating MythVideo with Miro video files failed." ) sys . exit ( 1 ) printStatistics ( ) return True