itch 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|