Updated copyright blurbs in all files to '# Copyright'
[hooke.git] / hooke / plugin / playlist.py
1 # Copyright
2
3 """The `playlist` module provides :class:`PlaylistPlugin` several
4 associated :class:`hooke.command.Command`\s for handling
5 :mod:`hooke.playlist` classes.
6 """
7
8 import glob
9
10 from ..command import Command, Argument, Failure
11 from ..playlist import FilePlaylist
12 from ..plugin import Builtin
13
14
15 class PlaylistPlugin (Builtin):
16     def __init__(self):
17         super(PlaylistPlugin, self).__init__(name='playlist')
18
19     def commands(self):
20         return [NextCommand(), PreviousCommand(), JumpCommand(),
21                 IndexCommand(), CurveListCommand(),
22                 SaveCommand(), LoadCommand(),
23                 AddCommand(), AddGlobCommand(),
24                 RemoveCommand(), FilterCommand(), NoteFilterCommand()]
25
26
27 # Define common or complicated arguments
28
29 def current_playlist_callback(hooke, command, argument, value):
30     if value != None:
31         return value
32     playlist = hooke.playlists.current()
33     if playlist == None:
34         raise Failure('No playlists loaded')
35     return playlist
36
37 PlaylistArgument = Argument(
38     name='playlist', type='playlist', callback=current_playlist_callback,
39     help="""
40 :class:`hooke.plugin.playlist.Playlist` to act on.  Defaults to the
41 current playlist.
42 """.strip())
43
44 def playlist_name_callback(hooke, command, argument, value):
45         return hooke.playlists.free_name()
46
47 PlaylistNameArgument = Argument(
48     name='name', type='string', optional=True, callback=playlist_name_callback,
49     help="""
50 Name of the new playlist (defaults to an auto-generated name).
51 """.strip())
52
53 def all_drivers_callback(hooke, command, argument, value):
54     return hooke.drivers
55
56
57 # Define commands
58
59 class NextCommand (Command):
60     """Move playlist to the next curve.
61     """
62     def __init__(self):
63         super(NextCommand, self).__init__(
64             name='next curve',
65             arguments=[PlaylistArgument],
66             help=self.__doc__)
67
68     def _run(self, hooke, inqueue, outqueue, params):
69         params['playlist'].next()
70
71 class PreviousCommand (Command):
72     """Move playlist to the previous curve.
73     """
74     def __init__(self):
75         super(PreviousCommand, self).__init__(
76             name='previous curve',
77             arguments=[PlaylistArgument],
78             help=self.__doc__)
79
80     def _run(self, hooke, inqueue, outqueue, params):
81         params['playlist'].previous()
82
83 class JumpCommand (Command):
84     """Move playlist to a given curve.
85     """
86     def __init__(self):
87         super(JumpCommand, self).__init__(
88             name='jump to curve',
89             arguments=[
90                 PlaylistArgument,
91                 Argument(name='index', type='int', optional=False, help="""
92 Index of target curve.
93 """.strip()),
94                 ],
95             help=self.__doc__)
96
97     def _run(self, hooke, inqueue, outqueue, params):
98         params['playlist'].jump(params['index'])
99
100 class IndexCommand (Command):
101     """Print the index of the current curve.
102
103     The first curve has index 0.
104     """
105     def __init__(self):
106         super(IndexCommand, self).__init__(
107             name='curve index',
108             arguments=[
109                 PlaylistArgument,
110                 ],
111             help=self.__doc__)
112
113     def _run(self, hooke, inqueue, outqueue, params):
114         outqueue.put(params['playlist']._index)
115
116 class CurveListCommand (Command):
117     """Get the curves in a playlist.
118     """
119     def __init__(self):
120         super(CurveListCommand, self).__init__(
121             name='playlist curves',
122             arguments=[
123                 PlaylistArgument,
124                 ],
125             help=self.__doc__)
126
127     def _run(self, hooke, inqueue, outqueue, params):
128         outqueue.put([c for c in params['playlist']])
129
130 class SaveCommand (Command):
131     """Save a playlist.
132     """
133     def __init__(self):
134         super(SaveCommand, self).__init__(
135             name='save playlist',
136             arguments=[
137                 PlaylistArgument,
138                 Argument(name='output', type='file',
139                          help="""
140 File name for the output playlist.  Defaults to overwriting the input
141 playlist.
142 """.strip()),
143                 ],
144             help=self.__doc__)
145
146     def _run(self, hooke, inqueue, outqueue, params):
147         params['playlist'].save(params['output'])
148
149 class LoadCommand (Command):
150     """Load a playlist.
151     """
152     def __init__(self):
153         super(LoadCommand, self).__init__(
154             name='load playlist',
155             arguments=[
156                 Argument(name='input', type='file', optional=False,
157                          help="""
158 File name for the input playlist.
159 """.strip()),
160                 Argument(name='drivers', type='driver', optional=True,
161                          count=-1, callback=all_drivers_callback,
162                          help="""
163 Drivers for loading curves.
164 """.strip()),
165                 ],
166             help=self.__doc__)
167
168     def _run(self, hooke, inqueue, outqueue, params):
169         p = FilePlaylist(drivers=params['drivers'], path=params['input'])
170         p.load()
171         hooke.playlists.append(p)
172         outqueue.put(p)
173
174 class AddCommand (Command):
175     """Add a curve to a playlist.
176     """
177     def __init__(self):
178         super(AddCommand, self).__init__(
179             name='add curve to playlist',
180             arguments=[
181                 PlaylistArgument,
182                 Argument(name='input', type='file', optional=False,
183                          help="""
184 File name for the input :class:`hooke.curve.Curve`.
185 """.strip()),
186                 Argument(name='info', type='dict', optional=True,
187                          help="""
188 Additional information for the input :class:`hooke.curve.Curve`.
189 """.strip()),
190                 ],
191             help=self.__doc__)
192
193     def _run(self, hooke, inqueue, outqueue, params):
194         params['playlist'].append_curve_by_path(params['input'],
195                                                 params['info'])
196
197 class AddGlobCommand (Command):
198     """Add curves to a playlist with file globbing.
199
200     Adding lots of files one at a time can be tedious.  With this
201     command you can use globs (`data/curves/*.dat`) to add curves
202     for all matching files at once.
203     """
204     def __init__(self):
205         super(AddGlobCommand, self).__init__(
206             name='glob curves to playlist',
207             arguments=[
208                 PlaylistArgument,
209                 Argument(name='input', type='glob', optional=False,
210                          help="""
211 File name glob for the input :class:`hooke.curve.Curve`.
212 """.strip()),
213                 Argument(name='info', type='dict', optional=True,
214                          help="""
215 Additional information for the input :class:`hooke.curve.Curve`.
216 """.strip()),
217                 ],
218             help=self.__doc__)
219
220     def _run(self, hooke, inqueue, outqueue, params):
221         for path in sorted(glob.glob(params['input'])):
222             params['playlist'].append_curve_by_path(path, params['info'])
223
224 class RemoveCommand (Command):
225     """Remove a curve from a playlist.
226     """
227     def __init__(self):
228         super(RemoveCommand, self).__init__(
229             name='remove curve from playlist',
230             arguments=[
231                 PlaylistArgument,
232                 Argument(name='index', type='int', optional=False, help="""
233 Index of target curve.
234 """.strip()),
235                 ],
236             help=self.__doc__)
237
238     def _run(self, hooke, inqueue, outqueue, params):
239         params['playlist'].pop(params['index'])
240         params['playlist'].jump(params._index)
241
242 class FilterCommand (Command):
243     """Create a subset playlist via a selection function.
244
245     Removing lots of curves one at a time can be tedious.  With this
246     command you can use a function `filter` to select the curves you
247     wish to keep.
248     """
249     def __init__(self):
250         super(FilterCommand, self).__init__(
251             name='filter playlist',
252             arguments=[
253                 PlaylistArgument,
254                 PlaylistNameArgument,
255                 Argument(name='filter', type='function', optional=False,
256                          help="""
257 Function returning `True` for "good" curves.  `filter(curve) -> True/False`.
258 """.strip()),
259                 ],
260             help=self.__doc__)
261
262     def _run(self, hooke, inqueue, outqueue, params):
263         p = params['playlist'].filter(params['filter'])
264         hooke.playlists.add(p)
265         outqueue.put(p)
266
267 class NoteFilterCommand (FilterCommand):
268     """Create a subset playlist of curves with `.info['note'] != None`.
269     """
270     def __init__(self):
271         super(NoteFilterCommand, self).__init__()
272         self.name = 'note filter playlist'
273         self.arguments = [a for a in self.arguments if a.name != 'filter']
274
275     def _run(self, hooke, inqueue, outqueue, params):
276         params['filter'] = lambda curve : \
277             'note' in curve.info and curve.info['note'] != None
278         return super(NoteFilterCommand, self)._run(
279             hooke, inqueue, outqueue, params)