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