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