Author: dmeyer
Date: Mon Oct 15 16:38:19 2007
New Revision: 9991

Log:
Reworked the directory configuration code and the num_* variables
of directories in beacon. MediaItem now support config: and cache:
variables and this will be stored in beacon. The config and cache
code will work for all items that define the needed beacon keys.


Modified:
   trunk/ui/share/skins/main/blurr.fxd
   trunk/ui/src/config.cxml
   trunk/ui/src/directory.py
   trunk/ui/src/menu/mediaitem.py

Modified: trunk/ui/share/skins/main/blurr.fxd
==============================================================================
--- trunk/ui/share/skins/main/blurr.fxd (original)
+++ trunk/ui/share/skins/main/blurr.fxd Mon Oct 15 16:38:19 2007
@@ -183,7 +183,7 @@
                            align="justified" expression="content"/>
                         <newline/>
                     </if>
-                    <if expression="not content and not plot">
+                    <if expression="not content and not plot and num_items">
                         <text font="info value" expression="num_items"/>
                         <text font="info value"> Items</text>
                         <!-- other values are num_play_items and num_dir_items 
-->

Modified: trunk/ui/src/config.cxml
==============================================================================
--- trunk/ui/src/config.cxml    (original)
+++ trunk/ui/src/config.cxml    Mon Oct 15 16:38:19 2007
@@ -12,18 +12,17 @@
                 How to sort the items in a directory. Valid values are
                 'name' (name of the item, maybe based on metadata), 'smart'
                 (like name but ignore "The" and "A" at the beginning),
-                'filename', 'date-old-first' and 'date-new-first'.
+                'filename' and 'date'.
             </desc>
             <values>
                 <value>name</value>
                 <value>smart</value>
                 <value>filename</value>
-                <value>date-old-first</value>
-                <value>date-new-first</value>
+                <value>date</value>
             </values>
         </var>
 
-        <var name="tvsort" default="date-old-first">
+        <var name="tvsort" default="date">
             <desc>
                 How to sort the items in a directory in the tv menu.
             </desc>
@@ -31,8 +30,7 @@
                 <value>name</value>
                 <value>smart</value>
                 <value>filename</value>
-                <value>date-old-first</value>
-                <value>date-new-first</value>
+                <value>date</value>
             </values>
         </var>
 

Modified: trunk/ui/src/directory.py
==============================================================================
--- trunk/ui/src/directory.py   (original)
+++ trunk/ui/src/directory.py   Mon Oct 15 16:38:19 2007
@@ -59,31 +59,13 @@
 # get logging object
 log = logging.getLogger()
 
-# variables for 'configure' submenu
-CONFIGURE = [
-    ('sort', _('Sort'),
-     _('How to sort items.')),
-    ('autoplay_single_item', _('Autoplay Single Item'),
-     _('Don\'t show directory if only one item exists and auto select the 
item.')),
-    ('autoplay_items', _('Autoplay Items'),
-     _('Autoplay the whole directory (as playlist) when it contains only 
files.')),
-    ('use_metadata', _('Use Tag Names'),
-     _('Use the names from the media files tags as display name.')),
-    ('sort_reverse', _('Reverse Sort'),
-     _('Show the items in the list in reverse order.')),
-    ('isplaylist', _('Is Playlist'),
-     _('Handle the directory as playlist and play the next item when ine is 
done.')) ,
-    ('hide_played', _('Hide Played Items'),
-     _('Hide items already played.'))]
-
-
 # get config object directory
 config = config.directory
 
 # register to beacon as string: on/off/auto
 kaa.beacon.register_file_type_attrs('dir',
-    freevo_num_items = (dict, kaa.beacon.ATTR_SIMPLE),
-    **dict([ ('freevo_' + x[0], (str, kaa.beacon.ATTR_SIMPLE)) for x in 
CONFIGURE ])
+    freevo_cache  = (list, kaa.beacon.ATTR_SIMPLE),
+    freevo_config = (dict, kaa.beacon.ATTR_SIMPLE),
 )
 
 def find_start_string(s1, s2):
@@ -136,25 +118,43 @@
             
         Playlist.__init__(self, parent=parent, type=type)
         self.item_menu  = None
-
-        if not isinstance(directory, kaa.beacon.Item):
-            raise AttributeError('%s is not beacon item' % directory)
-
         self.set_url(directory)
-
         self.files = Files()
         if directory.get('read_only'):
             self.files.read_only = True
         self.files.append(directory)
-
         if name:
             self.name = str_to_unicode(name)
-
         if self['show_all_items']:
             # FIXME: no way to set this
             self.media_type = None
+        self.query = None
         
 
+    @kaa.notifier.yield_execution()
+    def _calculate_num_items(self):
+        """
+        calculate the number of items in the directory.
+        """
+        log.info('create metainfo for %s', self.filename)
+        listing = kaa.beacon.query(parent=self.info)
+        if not listing.valid:
+            yield listing.wait()
+        listing = listing.get(filter='extmap')
+        mediatype = ''
+        if self.media_type:
+            media_type = '_%s' % self.media_type
+        num = 0
+        for p in MediaPlugin.plugins(self.media_type):
+            num += p.count(self, listing)
+        self['cache:num_play_items%s' % media_type] = num
+        self['cache:num_dir_items%s' % media_type] = 
len(listing.get('beacon:dir'))
+        self['cache:num_items%s' % media_type] = num + 
len(listing.get('beacon:dir'))
+        # update menu since we have the info now
+        # FIXME: what happens if a download is happening in that dir?
+        self.get_menustack().refresh()
+
+        
     def __getitem__(self, key):
         """
         return the specific attribute
@@ -163,29 +163,12 @@
             return _('Directory')
 
         if key.startswith('num_'):
-            # special keys to get number of playable items or the
-            # sum of all items in that directory
-            # get number of items info from beacon
-            num_items_all = self.info.get('freevo_num_items') or {}
-            num_items = num_items_all.get(self.media_type)
-            if num_items and num_items[0] != self.info.get('mtime'):
-                num_items = None
-            if not num_items:
-                log.info('create metainfo for %s', self.filename)
-                listing = 
kaa.beacon.query(parent=self.info).get(filter='extmap')
-                num_items = [ self.info.get('mtime'), 0 ]
-                for p in MediaPlugin.plugins(self.media_type):
-                    num_items[1] += p.count(self, listing)
-                num_items.append(len(listing.get('beacon:dir')))
-                if self.info.scanned():
-                    num_items_all[self.media_type] = num_items
-                    self.info['freevo_num_items'] = copy.copy(num_items_all)
-            if key == 'num_items':
-                return num_items[1] + num_items[2]
-            if key == 'num_play_items':
-                return num_items[1]
-            if key == 'num_dir_items':
-                return num_items[2]
+            if self.media_type:
+                key = 'cache:' + key + '_' + self.media_type
+            num = Playlist.__getitem__(self, key)
+            if num is None:
+                self._calculate_num_items()
+            return num
 
         if key in ( 'freespace', 'totalspace' ):
             s = os.statvfs(self.filename)
@@ -198,23 +181,30 @@
                 space='%s,%s' % (space / 1000, space % 1000)
             return space
 
-        if key.startswith('config:'):
-            value = self.info.get('tmp:%s' % key[7:])
+        if key.startswith('cfg:'):
+            value = self.info.get('tmp:%s' % key[4:])
             if value is not None:
+                # tmp override of that value
+                return value
+            # get config value from freevo_config
+            value = Playlist.__getitem__(self, key)
+            if value not in (None, 'auto'):
+                # value is set for this item
+                if value == 'on':
+                    return True
+                if value == 'off':
+                    return False
                 return value
-            value = self.info.get('freevo_%s' % key[7:])
-            if value and not value == 'auto':
-                if key == 'config:sort':
-                    return value
-                return value == 'yes'
             if isinstance(self.parent, DirItem):
+                # return the value from the parent (auto)
                 return self.parent[key]
-            if key == 'config:sort':
+            # auto and no parent, use config file values
+            if key == 'cfg:sort':
                 if self.menu_type == 'tv':
                     return config.tvsort
                 return config.sort
-            # config does not know about hide_played
-            value = getattr(config, key[7:], False)
+            # config files does not know about hide_played and reverse
+            value = getattr(config, key[4:], False)
             if isinstance(value, bool):
                 return value
             return self.media_type in value.split(',')
@@ -243,18 +233,19 @@
                 return Playlist.eventhandler(self, event)
 
             self.media_type = self.menu_type = type
+            # deactivate autoplay but not save it
             self['tmp:autoplay_single_item'] = False
             self.item_menu.autoselect = False
-            self.browse(update=True)
+            self.browse()
             OSD_MESSAGE.post('%s view' % type)
             return True
 
         if event == DIRECTORY_TOGGLE_HIDE_PLAYED:
-            self['tmp:hide_played'] = not self['config:hide_played']
+            self['cfg:hide_played'] = not self['cfg:hide_played']
             self['tmp:autoplay_single_item'] = False
             self.item_menu.autoselect = False
-            self.browse(update=True)
-            if self['config:hide_played']:
+            self.browse()
+            if self['cfg:hide_played']:
                 OSD_MESSAGE.post('Hide played items')
             else:
                 OSD_MESSAGE.post('Show all items')
@@ -274,7 +265,7 @@
         play = Action(_('Play all files in directory'), self.play)
 
         if self['num_items']:
-            if self['config:autoplay_items'] and not self['num_dir_items']:
+            if self['cfg:autoplay_items'] and not self['num_dir_items']:
                 items = [ play, browse ]
             else:
                 items = [ browse, play ]
@@ -320,7 +311,7 @@
         return
 
 
-    def browse(self, update=False, authstatus=0):
+    def browse(self):
         """
         build the items for the directory
         """
@@ -330,23 +321,27 @@
         dir_items  = []
         pl_items   = []
 
-        if update:
-            # Delete possible skin settings
-            # FIXME: This is a very bad handling, maybe signals?
-            if hasattr(self.item_menu, 'skin_default_has_description'):
-                del self.item_menu.skin_default_has_description
-            if hasattr(self.item_menu, 'skin_default_no_images'):
-                del self.item_menu.skin_default_no_images
+        # Delete possible skin settings
+        # FIXME: This is a very bad handling, maybe signals?
+        if hasattr(self.item_menu, 'skin_default_has_description'):
+            del self.item_menu.skin_default_has_description
+        if hasattr(self.item_menu, 'skin_default_no_images'):
+            del self.item_menu.skin_default_no_images
 
         elif not os.path.exists(self.filename):
             # FIXME: better handling!!!!!
            MessageWindow(_('Directory does not exist')).show()
             return
 
-        if not update:
+        if self.query is None:
             self.query = kaa.beacon.query(parent=self.info)
-            self.query.signals['changed'].connect_weak(self.browse, 
update=True)
+            self.query.signals['changed'].connect_weak(self.browse)
             self.query.monitor()
+            if not self.query.valid:
+                # the changed signal will be called when the listing
+                # is ready and this will trigger browse again.
+                return
+                
         listing = self.query.get(filter='extmap')
 
         #
@@ -371,7 +366,7 @@
         self.listing = listing
 
         # handle hide_played
-        if self['config:hide_played']:
+        if self['cfg:hide_played']:
             play_items = [ p for p in play_items if not 
p.info.get('last_played') ]
 
         # remove same beginning from all play_items
@@ -397,7 +392,7 @@
         def _sortfunc(m):
             return lambda l, o: cmp(l.sort(m), o.sort(m))
 
-        sorttype = self['config:sort']
+        sorttype = self['cfg:sort']
 
         # sort directories by name
         dir_items.sort(_sortfunc(sorttype))
@@ -410,33 +405,25 @@
             pl_items.sort(_sortfunc(sorttype))
 
         play_items.sort(_sortfunc(sorttype))
-        if sorttype == 'date-new-first':
-            # FIXME: this can never happen!
+        if self['cfg:reverse']:
             play_items.reverse()
 
         #
         # final settings
         #
 
-        # update num_items information if needed
-        num_items_all = self.info.get('freevo_num_items') or {}
-        num_items = num_items_all.get(self.media_type)
-        if num_items and (num_items[1] != len(play_items) + len(pl_items) or \
-                          num_items[2] != len(dir_items)):
-            num_items[1] = len(play_items) + len(pl_items)
-            num_items[2] = len(dir_items)
-            self.info['freevo_num_items'] = copy.copy(num_items_all)
-
+        # FIXME: update num items
+        # len(play_items), len(pl_items), len(dir_items)
 
         # add all playable items to the playlist of the directory
         # to play one files after the other
-        if self['config:isplaylist']:
+        if self['cfg:isplaylist']:
             self.set_playlist(play_items)
 
         # build a list of all items
         items = dir_items + pl_items + play_items
 
-        # random playlist (only active for audio)
+        # random playlist
         if self.menu_type and self.menu_type in \
                config.add_random_playlist and len(play_items) > 1:
             pl = Playlist(_('Random playlist'), play_items, self,
@@ -449,76 +436,38 @@
         # action
         #
 
-        if update:
+        if self.item_menu is not None:
+            # we could update it
             if self.item_menu:
+                # still in the stack
                 self.item_menu.set_items(items)
+                return
+            # weakref is gone
+            self.query = None
             return
 
         # normal menu build
         item_menu = menu.Menu(self.name, items, type = self.menu_type)
-        item_menu.autoselect = self['config:autoplay_single_item']
+        item_menu.autoselect = self['cfg:autoplay_single_item']
         self.get_menustack().pushmenu(item_menu)
         self.item_menu = weakref(item_menu)
 
-    # ======================================================================
-    # configure submenu
-    # ======================================================================
 
-
-    def configure_get_status(self, var):
-        """
-        return name for the configure menu
-        """
-        value = self.info.get('freevo_%s' % var.lower())
-        if var == 'sort':
-            return 'ICON_RIGHT_AUTO_' + _(value)
-        if value == 'yes':
-            return 'ICON_RIGHT_ON_' + _('on')
-        if value == 'no':
-            return 'ICON_RIGHT_OFF_' + _('off')
-        return 'ICON_RIGHT_AUTO_' + _('auto')
-
-
-    def configure_set_var(self, var):
-        """
-        Update the variable in var and change the menu. This function is used
-        by 'configure'
-        """
-        dbvar = 'freevo_%s' % var.lower()
-        current = self.info.get(dbvar) or 'auto'
-        if var == 'sort':
-            possible = ['auto', 'name', 'smart', 'filename', 'date']
-            if not current in possible or possible.index(current) == 
len(possible) - 1:
-                self.info[dbvar] = 'auto'
-            else:
-                self.info[dbvar] = possible[possible.index(current)+1]
-        elif current == 'auto':
-            self.info[dbvar] = 'yes'
-        elif current == 'yes':
-            self.info[dbvar] = 'no'
-        else:
-            self.info[dbvar] = 'auto'
-
-        # change name
-        item = self.get_menustack().get_selected()
-        item.name = item.name[:item.name.find(u'\t') + 1] + \
-                    self.configure_get_status(var)
-
-        # rebuild menu
-        self.get_menustack().refresh(True)
-
-
-    def configure(self):
-        """
-        show the configure dialog for folder specific settings
-        """
-        items = []
-        for i, name, descr in CONFIGURE:
-            name += '\t'  + self.configure_get_status(i)
-            action = ActionItem(name, self, self.configure_set_var, descr)
-            action.parameter(var=i)
-            items.append(action)
-        self.get_menustack().delete_submenu(False)
-        m = menu.Menu(_('Configure'), items)
-        m.table = (80, 20)
-        self.get_menustack().pushmenu(m)
+    def get_configure_items(self):
+        # variables for 'configure' submenu
+        # FIXME: put this outside the code somehow
+        return [
+            ('sort', _('Sort'), ('auto', 'name', 'smart', 'filename', 'date' ),
+             _('How to sort items.')),
+            ('reverse', _('Reverse Sort'), ('auto', 'on', 'off' ),
+             _('Show the items in the list in reverse order.')),
+            ('autoplay_single_item', _('Autoplay Single Item'), ('auto', 'on', 
'off' ),
+             _('Don\'t show directory if only one item exists and auto select 
it.')),
+            ('autoplay_items', _('Autoplay Items'), ('auto', 'on', 'off' ),
+             _('Autoplay the whole directory as playlist when it contains only 
files.')),
+            ('use_metadata', _('Use Tag Names'), ('auto', 'on', 'off' ),
+             _('Use the names from the media files tags as display name.')),
+            ('isplaylist', _('Is Playlist'), ('auto', 'on', 'off' ),
+             _('Handle the directory as playlist and play the next item when 
one is done.')) ,
+            ('hide_played', _('Hide Played Items'), ('auto', 'on', 'off' ),
+             _('Hide items already played.'))]

Modified: trunk/ui/src/menu/mediaitem.py
==============================================================================
--- trunk/ui/src/menu/mediaitem.py      (original)
+++ trunk/ui/src/menu/mediaitem.py      Mon Oct 15 16:38:19 2007
@@ -44,8 +44,9 @@
 from freevo.ui.event import PLAY_START, STOP
 
 # menu imports
-from item import Item
+from item import Item, ActionItem
 from files import Files
+from menu import Menu
 
 # get logging object
 log = logging.getLogger()
@@ -69,22 +70,11 @@
         Set a new url to the item and adjust all attributes depending
         on the url. Each MediaItem has to call this function.
         """
-        if isinstance(url, kaa.beacon.Item):
-            self.info = url
-            url = url.url
-        else:
-            log.error('FIXME: bad url %s', url)
-            self.info = {}
-
-            self.url = url              # the url itself
-            self.network_play = True    # network url, like http
-            self.filename     = ''      # filename if it's a file:// url
-            self.mode         = ''      # the type (file, http, dvd...)
-            self.files        = None    # Files
-            self.name         = u''
-            return
+        if not isinstance(url, kaa.beacon.Item):
+            raise RuntimeError('MediaItem.set_url needs a beacon item')
 
-        self.url = url
+        self.info = url
+        self.url = url.url
         self.files = Files()
         if self.info.get('read_only'):
             self.files.read_only = True
@@ -125,11 +115,28 @@
             return '%d:%02d:%02d' % ( time / 3600, (time % 3600) / 60, time % 
60)
         return '%02d:%02d' % (time / 60, time % 60)
 
-        
+
     def __getitem__(self, attr):
         """
         return the specific attribute
         """
+        if attr.startswith('cfg:'):
+            # freevo_config attribute in beacon
+            if not self.info.get('freevo_config'):
+                return None
+            return self['freevo_config'].get(attr[4:])
+
+        if attr.startswith('cache:'):
+            # freevo_config attribute in beacon
+            if not self.info.get('freevo_cache'):
+                return None
+            mtime, cache = self.info.get('freevo_cache')
+            if mtime == self.info.get('mtime'):
+                return cache.get(attr[6:])
+            # cache not up-to-date, delete it
+            self.info['freevo_cache'] = [ self.info.get('mtime'), {} ]
+            return
+            
         if attr == 'length':
             try:
                 return self.format_time(self.info.get('length'))
@@ -165,6 +172,36 @@
         return Item.__getitem__(self, attr)
 
 
+    def __setitem__(self, attr, value):
+        """
+        Set attribute to value.
+        """
+        if attr.startswith('cfg:'):
+            # freevo_config attribute in beacon
+            key = attr[4:]
+            if not self.info.get('freevo_config'):
+                self.info['freevo_config'] = {}
+            self.info['freevo_config'][key] = value
+            if self.info.get('tmp:%s' + key):
+                # remove tmp setting
+                self.info['tmp:%s' + key] = None
+            # FIXME: work sround Beacon bug!!!
+            self.info['freevo_config'] = dict(self.info['freevo_config'])
+            return
+
+        if attr.startswith('cache:'):
+            # freevo_config attribute in beacon
+            if not self.info.get('freevo_cache') or \
+                   self.info.get('freevo_cache')[0] != self.info.get('mtime'):
+                self.info['freevo_cache'] = [ self.info.get('mtime'), {} ]
+            self.info['freevo_cache'][1][attr[6:]] = value
+            # FIXME: work sround Beacon bug!!!
+            self.info['freevo_cache'] = self.info['freevo_cache'][:]
+            return
+
+        return Item.__setitem__(self, attr, value)
+
+
     def __id__(self):
         """
         Return a unique id of the item. This id should be the same when the
@@ -176,7 +213,7 @@
     def __repr__(self):
         name = str(self.__class__)
         return "<%s %s>" % (name[name.rfind('.')+1:-2], self.url)
-    
+
 
     def sort(self, mode='name'):
         """
@@ -216,3 +253,51 @@
         Stop playing
         """
         pass
+
+
+    # ======================================================================
+    # configure submenu
+    # ======================================================================
+
+
+    def get_configure_items(self):
+        """
+        Return configure options for this item.
+        """
+        raise RuntimeError('item can not be configured')
+
+
+    def _set_configure_var(self, var, name, choices):
+        """
+        Update the variable update the menu.
+        """
+        # update value
+        dbvar = 'cfg:%s' % var.lower()
+        current = MediaItem.__getitem__(self, dbvar) or 'auto'
+        current = choices[(choices.index(current) + 1) % len(choices)]
+        self[dbvar] = current
+        # change name
+        item = self.get_menustack().get_selected()
+        item.name = name + '\t'  + current
+        # rebuild menu
+        self.get_menustack().refresh(True)
+
+
+    def configure(self):
+        """
+        Show the configure dialog for the item.
+        """
+        items = []
+        for i, name, values, descr in self.get_configure_items():
+            dbvar = 'cfg:%s' % i.lower()
+            current = MediaItem.__getitem__(self, dbvar) or 'auto'
+            action = ActionItem(name + '\t'  + current, self,
+                                self._set_configure_var, descr)
+            action.parameter(var=i, name=name, choices=list(values))
+            items.append(action)
+        if not items:
+            return
+        self.get_menustack().delete_submenu(False)
+        m = Menu(_('Configure'), items)
+        m.table = (80, 20)
+        self.get_menustack().pushmenu(m)

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to