itch 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/itch +29 -16
- data/lib/itch.rb +51 -19
- metadata +2 -2
data/bin/itch
CHANGED
@@ -7,20 +7,33 @@ rescue LoadError
|
|
7
7
|
require 'itch'
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
begin
|
11
|
+
|
12
|
+
#Create an iTunes controller.
|
13
|
+
helper = Itch.new(Itch.create_itunes_interface)
|
14
|
+
|
15
|
+
#Get program options.
|
16
|
+
config = helper.parse_options(ARGV)
|
17
|
+
#Set default options.
|
18
|
+
config = helper.set_default_options(config)
|
19
|
+
#Get playlists that tracks will be selected from.
|
20
|
+
playlists = helper.get_playlists(config)
|
21
|
+
#Delete requested playlists.
|
22
|
+
helper.delete_playlists(config)
|
23
|
+
#Get tracks for processing.
|
24
|
+
tracks = helper.get_tracks(config, playlists)
|
25
|
+
#Process general commands.
|
26
|
+
helper.perform_general_operations(config)
|
27
|
+
#Process commands for specified tracks.
|
28
|
+
helper.perform_track_operations(config, tracks)
|
12
29
|
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
config
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#Process general commands.
|
24
|
-
helper.perform_general_operations(config)
|
25
|
-
#Process commands for specified tracks.
|
26
|
-
helper.perform_track_operations(config, tracks)
|
30
|
+
rescue => exception
|
31
|
+
|
32
|
+
#If debug mode requested, print backtrace to STDERR.
|
33
|
+
if config and config.has_key?('debug')
|
34
|
+
$stderr.puts exception.backtrace
|
35
|
+
end
|
36
|
+
#Print error to STDERR and exit with an abnormal status.
|
37
|
+
abort "Error: " + exception.message
|
38
|
+
|
39
|
+
end
|
data/lib/itch.rb
CHANGED
@@ -21,7 +21,11 @@ class Itch
|
|
21
21
|
|
22
22
|
#Create an OLE/COM link to iTunes.
|
23
23
|
def Itch.create_itunes_interface
|
24
|
-
|
24
|
+
begin
|
25
|
+
WIN32OLE.new('iTunes.Application') or raise "Couldn't take control of iTunes."
|
26
|
+
rescue WIN32OLERuntimeError => exception
|
27
|
+
raise exception.exception("Couldn't take control of iTunes. Could a prior instance be shutting down?")
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
|
@@ -31,13 +35,30 @@ class Itch
|
|
31
35
|
#Config will hold parsed option values.
|
32
36
|
config = Hash.new
|
33
37
|
|
34
|
-
#
|
38
|
+
#Set up option parser.
|
35
39
|
options = OptionParser.new
|
40
|
+
#Modify option parser to wrap descriptions.
|
41
|
+
class <<options
|
42
|
+
alias old_on on
|
43
|
+
def on (*opts, &block)
|
44
|
+
opts.map! do |option|
|
45
|
+
if option.class == String and option.length > 40
|
46
|
+
option = option.scan(/\S.{0,40}\S(?=\s|$)|\S+/)
|
47
|
+
end
|
48
|
+
option
|
49
|
+
end
|
50
|
+
old_on(*opts.flatten, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#Set up valid options.
|
55
|
+
|
36
56
|
options.separator("Program help:")
|
37
57
|
options.on("-h", "--help", TrueClass, "Display program help.") {
|
38
58
|
puts options.help
|
39
59
|
exit
|
40
60
|
}
|
61
|
+
|
41
62
|
options.separator("Playback controls:")
|
42
63
|
options.on("-p", "--play-pause", TrueClass, "If currently paused, begin playing. If currently playing, pause playback.") {|value| config['play-pause'] = value}
|
43
64
|
options.on("--pause", TrueClass, "Pause playback.") {|value| config['pause'] = value}
|
@@ -54,6 +75,7 @@ class Itch
|
|
54
75
|
options.on("--scan-backwards [seconds]", Integer, "Scan backwards X seconds within the current track (default 10).") {|value| config['scan-backwards'] = value || 10}
|
55
76
|
options.on("--scan-forwards [seconds]", Integer, "Scan forwards X seconds within the current track (default 10).") {|value| config['scan-forwards'] = value || 10}
|
56
77
|
options.on("--play-file name", Object, "Play the specified file or folder.") {|value| config['play-file'] = value}
|
78
|
+
|
57
79
|
options.separator("Info on selected tracks:")
|
58
80
|
options.on("-i", "--print-info format", Object, "For each track, print information in the given format. If the following strings appear in the given format, they will be replaced with the corresponding track information:",
|
59
81
|
%q#"%a": artist#,
|
@@ -79,12 +101,14 @@ class Itch
|
|
79
101
|
%q#"%y": year#,
|
80
102
|
%q#"%%": percent sign#
|
81
103
|
) {|value| config['print-info'] = value}
|
104
|
+
|
82
105
|
options.separator("General iTunes controls:")
|
83
106
|
options.on("-a", "--add-file name", Object, "Add the specified file or folder to the library.") {|value| (config['add-file'] ||= []) << value}
|
84
107
|
options.on("-q", "--quit", TrueClass, "Exit iTunes.") {|value| config['quit'] = value}
|
85
108
|
options.on("--open-url url", Object, "Open the given URL.") {|value| config['open-url'] = value}
|
86
109
|
options.on("--goto-store-home-page", TrueClass, "Go to the Store.") {|value| config['goto-store-home-page'] = value}
|
87
110
|
options.on("--update-ipod", TrueClass, "Update the iPod.") {|value| config['update-ipod'] = value}
|
111
|
+
|
88
112
|
options.separator("Playlist selection:")
|
89
113
|
options.on("--library", TrueClass, "Operation will include the entire iTunes library. Used by default unless other libraries are selected.") {|value| config['library'] = value}
|
90
114
|
options.on("--current-playlist", TrueClass, "Operation will include the current playlist.") {|value| config['current-playlist'] = value}
|
@@ -92,6 +116,7 @@ class Itch
|
|
92
116
|
options.on("--all-playlists", TrueClass, "Operation will include all playlists.") {|value| config['all-playlists'] = value}
|
93
117
|
options.on("--create-playlist name", Object, "Create a playlist with the specified name and include it in the operation. (This option can occur more than once.)") {|value| (config['create-playlist'] ||= []) << value}
|
94
118
|
options.on("--delete-playlist name", Object, "Delete the playlist with the specified name. (This option can occur more than once.)") {|value| (config['delete-playlist'] ||= []) << value}
|
119
|
+
|
95
120
|
options.separator("Track selection:")
|
96
121
|
options.on("-f", "--find string", Object, "Operation will include all tracks in the specified playlist(s) where any field matches the specified string. (This option can occur more than once.)") {|value| (config['find'] ||= []) << value}
|
97
122
|
options.on("-c", "--current-track", TrueClass, "Operation will inclue the current track.") {|value| config['current-track'] = value}
|
@@ -103,6 +128,7 @@ class Itch
|
|
103
128
|
options.on("--find-composer string", Object, "Operation will include all tracks in the specified playlist(s) where the composer matches the specified string. (This option can occur more than once.)") {|value| (config['find-composer'] ||= []) << value}
|
104
129
|
options.on("--find-track-name string", Object, "Operation will include all tracks in the specified playlist(s) where the track name matches the specified string. (This option can occur more than once.)") {|value| (config['find-track-name'] ||= []) << value}
|
105
130
|
options.on("-F", "--play-found", TrueClass, "Play the first of the selected tracks.") {|value| config['play-found'] = value}
|
131
|
+
|
106
132
|
options.separator("Set track info:")
|
107
133
|
options.on("--set-artist name", Object, "Set the artist for each track.") {|value| config['set-artist'] = value}
|
108
134
|
options.on("--set-album name", Object, "Set the album for each track.") {|value| config['set-album'] = value}
|
@@ -125,6 +151,9 @@ class Itch
|
|
125
151
|
options.on("--set-track-volume percent", Integer, "Set the volume adjustment percentage for each track, from -100 to 100. Negative numbers decrease the volume, positive numbers increase it. 0 means no adjustment.") {|value| config['set-track-volume'] = value}
|
126
152
|
options.on("--set-year number", Integer, "Set the year of publication for each track.") {|value| config['set-year'] = value}
|
127
153
|
|
154
|
+
options.separator("Troubleshooting:")
|
155
|
+
options.on("--debug", TrueClass, "When an error occurs, show a more detailed message.") {|value| config['debug'] = value}
|
156
|
+
|
128
157
|
#Parse the options, printing usage if parsing fails.
|
129
158
|
options.parse(arguments) rescue puts "#{$!}\nType '#{$0} --help' for valid options."
|
130
159
|
|
@@ -152,24 +181,24 @@ class Itch
|
|
152
181
|
def get_playlists (config)
|
153
182
|
|
154
183
|
playlists = Array.new
|
155
|
-
playlists
|
184
|
+
playlists << @interface.LibraryPlaylist if config['library']
|
156
185
|
if config['current-playlist']
|
157
|
-
playlists
|
186
|
+
playlists << @interface.CurrentPlaylist or raise "Can't find current playlist."
|
158
187
|
end
|
159
188
|
if config['all-playlists']
|
160
189
|
if library_playlists = @interface.LibrarySource.Playlists
|
161
|
-
library_playlists.each {|playlist| playlists
|
190
|
+
library_playlists.each {|playlist| playlists << playlist}
|
162
191
|
else
|
163
192
|
raise "No playlists found."
|
164
193
|
end
|
165
194
|
end
|
166
195
|
with_option_values('playlist', config) do |name|
|
167
|
-
playlists
|
196
|
+
playlists << find_playlist(name) or raise "Can't find playlist #{name}"
|
168
197
|
end
|
169
198
|
|
170
199
|
#If creation of playlist(s) requested, create them and add to the collection.
|
171
200
|
with_option_values('create-playlist', config) do |name|
|
172
|
-
playlists
|
201
|
+
playlists << @interface.CreatePlaylist(name) or raise "Can't create playlist #{name}"
|
173
202
|
end
|
174
203
|
|
175
204
|
playlists
|
@@ -188,34 +217,37 @@ class Itch
|
|
188
217
|
#Find requested tracks.
|
189
218
|
def get_tracks (config, playlists)
|
190
219
|
|
191
|
-
tracks =
|
192
|
-
|
220
|
+
tracks = []
|
221
|
+
|
193
222
|
#Add current track to list if desired.
|
194
223
|
if config['current-track']
|
195
|
-
|
224
|
+
current_track = @interface.CurrentTrack or raise "No currently active/playing track." #"x << y.CurrentTrack or raise" won't work; nil is false but [nil] is true.
|
225
|
+
tracks << current_track
|
196
226
|
end
|
197
|
-
|
227
|
+
|
198
228
|
#Add highlighted tracks to list if desired.
|
199
229
|
if config['selected-tracks']
|
200
230
|
if selected_tracks = @interface.SelectedTracks
|
201
|
-
selected_tracks.each {|track| tracks
|
231
|
+
selected_tracks.each {|track| tracks << track}
|
202
232
|
else
|
203
233
|
raise "No tracks selected."
|
204
234
|
end
|
205
235
|
end
|
206
236
|
|
207
237
|
#Find tracks in selected playlists.
|
208
|
-
|
238
|
+
playlists.each do |playlist|
|
209
239
|
|
210
240
|
#If all tracks are to be processed, select them all.
|
211
241
|
if config['all-tracks']
|
212
|
-
playlist.Tracks.each {|track| tracks
|
242
|
+
playlist.Tracks.each {|track| tracks << track}
|
213
243
|
#Otherwise, see if user wishes to search for tracks.
|
214
244
|
else
|
215
245
|
search_playlist = lambda {|option, field_id|
|
216
246
|
with_option_values(option, config) do |terms|
|
217
247
|
if (results = playlist.Search(terms, field_id))
|
218
|
-
results.each {|track| tracks
|
248
|
+
results.each {|track| tracks << track}
|
249
|
+
else
|
250
|
+
raise "No tracks found."
|
219
251
|
end
|
220
252
|
end
|
221
253
|
}
|
@@ -229,7 +261,7 @@ class Itch
|
|
229
261
|
|
230
262
|
#Import files to library and add resulting tracks to list.
|
231
263
|
with_option_values('add-file', config) do |path|
|
232
|
-
tracks.concat(add_file(path, playlist))
|
264
|
+
tracks.concat(add_file(File.expand_path(path), playlist))
|
233
265
|
end
|
234
266
|
|
235
267
|
end
|
@@ -269,7 +301,7 @@ class Itch
|
|
269
301
|
def perform_track_operations (config, tracks)
|
270
302
|
|
271
303
|
#Operate on selected tracks.
|
272
|
-
|
304
|
+
tracks.each do |track|
|
273
305
|
specified?(config, 'set-artist') {|v| track.Artist = v}
|
274
306
|
specified?(config, 'set-album') {|v| track.Album = v}
|
275
307
|
specified?(config, 'set-bpm') {|v| track.BPM = v}
|
@@ -328,7 +360,7 @@ class Itch
|
|
328
360
|
segment.gsub!(/%s/) {track.SkippedCount.to_s}
|
329
361
|
segment.gsub!(/%t/) {track.TrackNumber.to_s}
|
330
362
|
segment.gsub!(/%T/) {track.TrackCount.to_s}
|
331
|
-
segment.gsub!(/%v/) {track.VolumeAdjustment.to_s}
|
363
|
+
segment.gsub!(/%v/) {volume = track.VolumeAdjustment; (1 .. 98).include?(volume) ? volume.next.to_s : volume.to_s}
|
332
364
|
segment.gsub!(/%y/) {track.Year.to_s}
|
333
365
|
segment
|
334
366
|
end
|
@@ -363,7 +395,7 @@ class Itch
|
|
363
395
|
sleep 1 while status.InProgress
|
364
396
|
#Return added track(s).
|
365
397
|
tracks = Array.new
|
366
|
-
status.Tracks.each {|track| tracks
|
398
|
+
status.Tracks.each {|track| tracks << track}
|
367
399
|
tracks
|
368
400
|
end
|
369
401
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: itch
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
date: 2007-05-
|
6
|
+
version: 1.0.4
|
7
|
+
date: 2007-05-08 00:00:00 -07:00
|
8
8
|
summary: Allows control of iTunes for Windows via a command line.
|
9
9
|
require_paths:
|
10
10
|
- lib
|