X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=hooke%2Fplugin%2Fplaylist.py;h=9f0d9e15674abdd79c21a3587ebae183aa18b18e;hb=d396dd234bf97b6159ce0afcc816874c781b6659;hp=371cd1e4573bad145535dae54ef1449193764b28;hpb=933dd93987018f3842575092f069e991e6682764;p=hooke.git diff --git a/hooke/plugin/playlist.py b/hooke/plugin/playlist.py index 371cd1e..9f0d9e1 100644 --- a/hooke/plugin/playlist.py +++ b/hooke/plugin/playlist.py @@ -2,15 +2,15 @@ # # This file is part of Hooke. # -# Hooke is free software: you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation, either -# version 3 of the License, or (at your option) any later version. +# Hooke is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. # -# Hooke is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. +# Hooke is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with Hooke. If not, see @@ -22,6 +22,7 @@ several associated :class:`hooke.command.Command`\s for handling """ import glob +import os.path from ..command import Command, Argument, Failure from ..playlist import FilePlaylist @@ -31,13 +32,12 @@ from ..plugin import Builtin class PlaylistPlugin (Builtin): def __init__(self): super(PlaylistPlugin, self).__init__(name='playlist') - - def commands(self): - return [NextCommand(), PreviousCommand(), JumpCommand(), - IndexCommand(), CurveListCommand(), - SaveCommand(), LoadCommand(), - AddCommand(), AddGlobCommand(), - RemoveCommand(), FilterCommand(), NoteFilterCommand()] + self._commands = [ + NextCommand(self), PreviousCommand(self), JumpCommand(self), + GetCommand(self), IndexCommand(self), CurveListCommand(self), + SaveCommand(self), LoadCommand(self), + AddCommand(self), AddGlobCommand(self), + RemoveCommand(self), FilterCommand(self), NoteFilterCommand(self)] # Define common or complicated arguments @@ -58,7 +58,15 @@ playlist. """.strip()) def playlist_name_callback(hooke, command, argument, value): - return hooke.playlists.free_name() + if value != None: + return value + i = 0 + names = [p.name for p in hooke.playlists] + while True: + name = 'playlist-%d' % i + if name not in names: + return name + i += 1 PlaylistNameArgument = Argument( name='name', type='string', optional=True, callback=playlist_name_callback, @@ -75,11 +83,11 @@ def all_drivers_callback(hooke, command, argument, value): class NextCommand (Command): """Move playlist to the next curve. """ - def __init__(self): + def __init__(self, plugin): super(NextCommand, self).__init__( name='next curve', arguments=[PlaylistArgument], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].next() @@ -87,11 +95,11 @@ class NextCommand (Command): class PreviousCommand (Command): """Move playlist to the previous curve. """ - def __init__(self): + def __init__(self, plugin): super(PreviousCommand, self).__init__( name='previous curve', arguments=[PlaylistArgument], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].previous() @@ -99,7 +107,7 @@ class PreviousCommand (Command): class JumpCommand (Command): """Move playlist to a given curve. """ - def __init__(self): + def __init__(self, plugin): super(JumpCommand, self).__init__( name='jump to curve', arguments=[ @@ -108,7 +116,7 @@ class JumpCommand (Command): Index of target curve. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].jump(params['index']) @@ -118,35 +126,45 @@ class IndexCommand (Command): The first curve has index 0. """ - def __init__(self): + def __init__(self, plugin): super(IndexCommand, self).__init__( name='curve index', arguments=[ PlaylistArgument, ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) + + def _run(self, hooke, inqueue, outqueue, params): + outqueue.put(params['playlist'].index()) + +class GetCommand (Command): + """Return a :class:`hooke.playlist.Playlist`. + """ + def __init__(self, plugin): + super(GetCommand, self).__init__( + name='get playlist', + arguments=[PlaylistArgument], + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - outqueue.put(params['playlist']._index) + outqueue.put(params['playlist']) class CurveListCommand (Command): """Get the curves in a playlist. """ - def __init__(self): + def __init__(self, plugin): super(CurveListCommand, self).__init__( name='playlist curves', - arguments=[ - PlaylistArgument, - ], - help=self.__doc__) + arguments=[PlaylistArgument], + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): - outqueue.put([c for c in params['playlist']]) + outqueue.put(list(params['playlist'])) class SaveCommand (Command): """Save a playlist. """ - def __init__(self): + def __init__(self, plugin): super(SaveCommand, self).__init__( name='save playlist', arguments=[ @@ -154,10 +172,11 @@ class SaveCommand (Command): Argument(name='output', type='file', help=""" File name for the output playlist. Defaults to overwriting the input -playlist. +playlist. If the playlist does not have an input file (e.g. it was +created from scratch with 'new playlist'), this option is required. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].save(params['output']) @@ -165,7 +184,7 @@ playlist. class LoadCommand (Command): """Load a playlist. """ - def __init__(self): + def __init__(self, plugin): super(LoadCommand, self).__init__( name='load playlist', arguments=[ @@ -179,7 +198,7 @@ File name for the input playlist. Drivers for loading curves. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): p = FilePlaylist(drivers=params['drivers'], path=params['input']) @@ -190,7 +209,7 @@ Drivers for loading curves. class AddCommand (Command): """Add a curve to a playlist. """ - def __init__(self): + def __init__(self, plugin): super(AddCommand, self).__init__( name='add curve to playlist', arguments=[ @@ -204,7 +223,7 @@ File name for the input :class:`hooke.curve.Curve`. Additional information for the input :class:`hooke.curve.Curve`. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].append_curve_by_path(params['input'], @@ -217,12 +236,12 @@ class AddGlobCommand (Command): command you can use globs (`data/curves/*.dat`) to add curves for all matching files at once. """ - def __init__(self): + def __init__(self, plugin): super(AddGlobCommand, self).__init__( name='glob curves to playlist', arguments=[ PlaylistArgument, - Argument(name='input', type='glob', optional=False, + Argument(name='input', type='string', optional=False, help=""" File name glob for the input :class:`hooke.curve.Curve`. """.strip()), @@ -231,7 +250,7 @@ File name glob for the input :class:`hooke.curve.Curve`. Additional information for the input :class:`hooke.curve.Curve`. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): for path in sorted(glob.glob(params['input'])): @@ -240,7 +259,7 @@ Additional information for the input :class:`hooke.curve.Curve`. class RemoveCommand (Command): """Remove a curve from a playlist. """ - def __init__(self): + def __init__(self, plugin): super(RemoveCommand, self).__init__( name='remove curve from playlist', arguments=[ @@ -249,11 +268,11 @@ class RemoveCommand (Command): Index of target curve. """.strip()), ], - help=self.__doc__) + help=self.__doc__, plugin=plugin) def _run(self, hooke, inqueue, outqueue, params): params['playlist'].pop(params['index']) - params['playlist'].jump(params._index) + params['playlist'].jump(params.index()) class FilterCommand (Command): """Create a subset playlist via a selection function. @@ -261,35 +280,52 @@ class FilterCommand (Command): Removing lots of curves one at a time can be tedious. With this command you can use a function `filter` to select the curves you wish to keep. + + Notes + ----- + There are issues with pickling functions bound to class + attributes, because the pickle module doesn't know where those + functions were originally defined (where it should point the + loader). Because of this, subclasses with hard-coded filter + functions are encouraged to define their filter function as a + method of their subclass. See, for example, + :meth:`NoteFilterCommand.filter`. """ - def __init__(self): + def __init__(self, plugin, name='filter playlist'): super(FilterCommand, self).__init__( - name='filter playlist', + name=name, arguments=[ PlaylistArgument, PlaylistNameArgument, + ], + help=self.__doc__, plugin=plugin) + if not hasattr(self, 'filter'): + self.arguments.append( Argument(name='filter', type='function', optional=False, help=""" -Function returning `True` for "good" curves. `filter(curve) -> True/False`. -""".strip()), - ], - help=self.__doc__) +Function returning `True` for "good" curves. +`filter(curve, hooke, inqueue, outqueue, params) -> True/False`. +""".strip())) def _run(self, hooke, inqueue, outqueue, params): - p = params['playlist'].filter(params['filter']) - hooke.playlists.add(p) + if not hasattr(self, 'filter'): + filter_fn = params['filter'] + else: + filter_fn = self.filter + p = params['playlist'].filter(filter_fn, + hooke=hooke, inqueue=inqueue, outqueue=outqueue, params=params) + p.name = params['name'] + if hasattr(p, 'path') and p.path != None: + p.set_path(os.path.join(os.path.dirname(p.path), p.name)) + hooke.playlists.append(p) outqueue.put(p) class NoteFilterCommand (FilterCommand): """Create a subset playlist of curves with `.info['note'] != None`. """ - def __init__(self): - super(NoteFilterCommand, self).__init__() - self.name = 'note filter playlist' - self.arguments = [a for a in self.arguments if a.name != 'filter'] + def __init__(self, plugin): + super(NoteFilterCommand, self).__init__( + plugin, name='note filter playlist') - def _run(self, hooke, inqueue, outqueue, params): - params['filter'] = lambda curve : \ - 'note' in curve.info and curve.info['note'] != None - return super(NoteFilterCommand, self)._run( - hooke, inqueue, outqueue, params) + def filter(self, curve, hooke, inqueue, outqueue, params): + return 'note' in curve.info and curve.info['note'] != None