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