Example #1
0
    def __init__( self):
        log('Creating gPodderLib()', sender=self)
        if gpodder.interface == gpodder.MAEMO:
            gpodder_dir='/media/mmc2/gpodder/'
            self.osso_c=osso.Context('gpodder_osso_sender', '1.0', False)
        else:
            gpodder_dir=os.path.expanduser('~/.config/gpodder/')
        util.make_directory( gpodder_dir)

        self.tempdir=gpodder_dir
        self.feed_cache_file=os.path.join(gpodder_dir, 'feedcache.pickle.db')
        self.channel_settings_file=os.path.join(gpodder_dir, 'channelsettings.pickle.db')
        self.episode_metainfo_file=os.path.join(gpodder_dir, 'episodemetainfo.pickle.db')

        self.channel_opml_file=os.path.join(gpodder_dir, 'channels.opml')
        self.channel_xml_file=os.path.join(gpodder_dir, 'channels.xml')

        if os.path.exists(self.channel_xml_file) and not os.path.exists(self.channel_opml_file):
            log('Trying to migrate channel list (channels.xml => channels.opml)', sender=self)
            self.migrate_channels_xml()

        self.config=config.Config( os.path.join( gpodder_dir, 'gpodder.conf'))
        util.make_directory(self.config.bittorrent_dir)

        # We need to make a seamless upgrade, so by default the video player is not specified
        # so the first time this application is run it will detect this and set it to the same 
        # as the audio player.  This keeps gPodder functionality identical to that prior to the 
        # upgrade.   The user can then set a specific video player if they so wish.	
        if self.config.videoplayer == 'unspecified':
            self.config.videoplayer=self.config.player	

        self.__download_history=HistoryStore( os.path.join( gpodder_dir, 'download-history.txt'))
        self.__playback_history=HistoryStore( os.path.join( gpodder_dir, 'playback-history.txt'))
        self.__locked_history=HistoryStore( os.path.join( gpodder_dir, 'lock-history.txt'))
Example #2
0
    def migrate_channels_xml(self):
        """Migrate old (gPodder < 0.9.5) channels.xml to channels.opml

        This function does a one-time conversion of the old
        channels.xml file format to the new (supported by
        0.9.5, the default on 0.10.0) channels.opml format.
        """
        def channels_xml_iter(filename='channels.xml'):
            for e in xml.dom.minidom.parse(filename).getElementsByTagName('url'):
                yield ''.join(n.data for n in e.childNodes if n.nodeType==n.TEXT_NODE)
        
        def create_outline(doc, url):
            outline=doc.createElement('outline')
            for w in (('title', ''), ('text', ''), ('xmlUrl', url), ('type', 'rss')):
                outline.setAttribute(*w)
            return outline
        
        def export_opml(urls, filename='channels.opml'):
            doc=xml.dom.minidom.Document()
            opml=doc.createElement('opml')
            opml.setAttribute('version', '1.1')
            doc.appendChild(opml)
            body=doc.createElement('body')
            for url in urls:
                body.appendChild(create_outline(doc, url))
            opml.appendChild(body)
            open(filename,'w').write(doc.toxml(encoding='utf-8'))
        
        try:
            export_opml(channels_xml_iter(self.channel_xml_file), self.channel_opml_file)
            shutil.move(self.channel_xml_file, self.channel_xml_file+'.converted')
            log('Successfully converted channels.xml to channels.opml', sender=self)
        except:
            log('Cannot convert old channels.xml to channels.opml', traceback=True, sender=self)
Example #3
0
 def save_to_file( self):
     if len( self):
         fp=open( self.filename, 'w')
         for url in self:
             fp.write( url + "\n")
         fp.close()
         log( 'Wrote %d history entries.', len( self), sender=self)
Example #4
0
    def playback_episode( self, channel, episode):
        self.history_mark_played( episode.url)
        filename=episode.local_filename()

        if gpodder.interface == gpodder.MAEMO and not self.config.maemo_allow_custom_player:
            # Use the built-in Nokia Mediaplayer here
            filename=filename.encode('utf-8')
            osso_rpc=osso.Rpc(self.osso_c)
            service='com.nokia.mediaplayer'
            path='/com/nokia/mediaplayer'
            osso_rpc.rpc_run(service, path, service, 'mime_open', ('file://'+filename,))
            return (True, service)

        # Determine the file type and set the player accordingly.  
        file_type=util.file_type_by_extension(util.file_extension_from_url(episode.url))

        if file_type == 'video':
            player=self.config.videoplayer
        elif file_type == 'audio':
            player=self.config.player
        else:
            log('Non-audio or video file type, using xdg-open for %s', filename, sender=self)
            player='xdg-open'
 
        command_line=shlex.split(util.format_desktop_command(player, filename).encode('utf-8'))
        log( 'Command line: [ %s ]', ', '.join( [ '"%s"' % p for p in command_line ]), sender=self)
        try:
            subprocess.Popen( command_line)
        except:
            return ( False, command_line[0] )
        return ( True, command_line[0] )
Example #5
0
 def get_device_name( self):
     if self.config.device_type == 'ipod':
         return _('iPod')
     elif self.config.device_type == 'filesystem':
         return _('MP3 player')
     else:
         log( 'Warning: Called get_device_name() when no device was selected.', sender=self)
         return '(unknown device)'
def update_metadata_on_file( filename, **metadata):
    global tag_update_methods

    ext=filename[-3:]
    if ext in tag_update_methods:
        log('Updating tag for %s', filename)
        return tag_update_methods[ext]( filename, **metadata)

    log('Do not know how to update file extension %s :/', ext)
    return False
Example #7
0
    def set_download_dir( self, new_downloaddir):
        if self.config.download_dir != new_downloaddir:
            log( 'Moving downloads from %s to %s', self.config.download_dir, new_downloaddir)
            try:
                # Fix error when moving over disk boundaries
                if os.path.isdir( new_downloaddir) and not os.listdir( new_downloaddir):
                    os.rmdir( new_downloaddir)

                shutil.move( self.config.download_dir, new_downloaddir)
            except:
                log( 'Error while moving %s to %s.', self.config.download_dir, new_downloaddir)
                return

        self.config.download_dir=new_downloaddir
def update_tag_ogg( filename, **metadata):
    data='\n'.join( [ '%s=%s' % ( i.upper(), metadata[i] ) for i in metadata ] + [''])

    p=subprocess.Popen3('vorbiscomment -w "%s"' % filename)

    writer=p.tochild
    writer.write(data)
    writer.close()

    result=p.wait() == 0

    if not result:
        log('Error while running vorbiscomment. Is it installed?! (vorbis-tools)')

    return result
Example #9
0
    def del_item( self, data, autosave=True):
        affected=0
        if data and type( data) is types.ListType:
            # Support passing a list of urls to this function
            for url in data:
                affected=affected + self.del_item( url, autosave=False)
        else:
            if data in self:
                log( 'Removing: %s', data, sender=self)
                self.remove( data)
                affected=affected + 1

        if affected and autosave:
            self.save_to_file()

        return affected
Example #10
0
def update_tag_mp3( filename, **metadata):
    if not has_eyed3:
        log('eyeD3 not found -> please install. no tags have been updated.')
        return False

    tag=eyeD3.tag.Tag( fileName=filename)
    tag.remove( eyeD3.tag.ID3_ANY_VERSION)
    tag.setVersion( eyeD3.tag.ID3_ANY_VERSION)

    for key in metadata:
        if key.lower() == 'artist':
            tag.setArtist( metadata[key])
        elif key.lower() == 'title':
            tag.setTitle( metadata[key])
        elif key.lower() == 'album':
            tag.setAlbum( metadata[key])

    return tag.update( eyeD3.tag.ID3_V2) == 1 and tag.update( eyeD3.tag.ID3_V1) == 1
Example #11
0
 def image_download_thread( self, url, callback_pixbuf=None, callback_status=None, callback_finished=None, cover_file=None):
     if callback_status is not None:
         util.idle_add(callback_status, _('Downloading podcast cover...'))
     pixbuf=gtk.gdk.PixbufLoader()
     
     if cover_file is None:
         log( 'Downloading %s', url)
         pixbuf.write( urllib.urlopen(url).read())
     
     if cover_file is not None and not os.path.exists(cover_file):
         log( 'Downloading cover to %s', cover_file)
         cachefile=open( cover_file, "w")
         cachefile.write( urllib.urlopen(url).read())
         cachefile.close()
     
     if cover_file is not None:
         log( 'Reading cover from %s', cover_file)
         try:
             pixbuf.write( open( cover_file, "r").read())
         except:
             # Probably a data error, delete temp file
             log('Data error while reading pixbuf. Deleting %s', cover_file, sender=self)
             util.delete_file(cover_file)
     
     try:
         pixbuf.close()
     except:
         # data error, delete temp file
         util.delete_file( cover_file)
     
     MAX_SIZE=400
     if callback_pixbuf is not None:
         pb=pixbuf.get_pixbuf()
         if pb:
             if pb.get_width() > MAX_SIZE:
                 factor=MAX_SIZE*1.0/pb.get_width()
                 pb=pb.scale_simple( int(pb.get_width()*factor), int(pb.get_height()*factor), gtk.gdk.INTERP_BILINEAR)
             if pb.get_height() > MAX_SIZE:
                 factor=MAX_SIZE*1.0/pb.get_height()
                 pb=pb.scale_simple( int(pb.get_width()*factor), int(pb.get_height()*factor), gtk.gdk.INTERP_BILINEAR)
             util.idle_add(callback_pixbuf, pb)
     if callback_status is not None:
         util.idle_add(callback_status, '')
     if callback_finished is not None:
         util.idle_add(callback_finished)
Example #12
0
    def clean_up_downloads( self, delete_partial=False):
        # Clean up temporary files left behind by old gPodder versions
        if delete_partial:
            temporary_files=glob.glob( '%s/*/.tmp-*' % ( self.downloaddir, ))
            for tempfile in temporary_files:
                util.delete_file( tempfile)

        # Clean up empty download folders
        download_dirs=glob.glob( '%s/*' % ( self.downloaddir, ))
        for ddir in download_dirs:
            if os.path.isdir( ddir):
                globr=glob.glob( '%s/*' % ( ddir, ))
                if not globr and ddir != self.config.bittorrent_dir:
                    log( 'Stale download directory found: %s', os.path.basename( ddir))
                    try:
                        os.rmdir( ddir)
                        log( 'Successfully removed %s.', ddir)
                    except:
                        log( 'Could not remove %s.', ddir)
Example #13
0
    def invoke_torrent( self, url, torrent_filename, target_filename):
        self.history_mark_played( url)

        if self.config.use_gnome_bittorrent:
            if util.find_command('gnome-btdownload') is None:
                log( 'Cannot find "gnome-btdownload". Please install gnome-bittorrent.', sender=self)
                return False

            command='gnome-btdownload "%s" --saveas "%s"' % ( torrent_filename, os.path.join( self.config.bittorrent_dir, target_filename))
            log( command, sender=self)
            os.system( '%s &' % command)
            return True
        else:
            # Simply copy the .torrent with a suitable name
            try:
                target_filename=os.path.join( self.config.bittorrent_dir, os.path.splitext( target_filename)[0] + '.torrent')
                shutil.copyfile( torrent_filename, target_filename)
                return True
            except:
                log( 'Torrent copy failed: %s => %s.', torrent_filename, target_filename)

        return False
Example #14
0
#
#


# for ogg/vorbis (vorbiscomment utility)
import subprocess

# for logging
from liblogger import log

# for mp3 files
has_eyed3=True
try:
    import eyeD3
except:
    log('(tagupdate) eyed3 not found -- tag update disabled')
    has_eyed3=False

# do we provide tagging functions to the user?
def tagging_supported():
    global has_eyed3
    return has_eyed3


tag_update_methods={}

def update_metadata_on_file( filename, **metadata):
    global tag_update_methods

    ext=filename[-3:]
    if ext in tag_update_methods:
Example #15
0
 def __init__( self, filename):
     self.filename=filename
     try:
         self.read_from_file()
     except:
         log( 'Creating new history list.', sender=self)