spfy 0.2.2 → 0.3.0

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.
Files changed (7) hide show
  1. checksums.yaml +6 -14
  2. data/README.md +24 -22
  3. data/bin/spfy +2 -1
  4. data/lib/spfy.rb +108 -201
  5. data/spfy.gemspec +12 -12
  6. data/test.sh +36 -0
  7. metadata +8 -7
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZWYwZjMxOGMyZjUyYzlhZGU2MDc0NTllYTFiMGUzMWMyNTY0YWY3Nw==
5
- data.tar.gz: !binary |-
6
- MWUyMGIyZTQwNGUwNGU4M2IwNWQyOTNkY2FjZDljZjRlYmQwMzkzOA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- Y2MzMzQzZmYwOGJmYmU1OTRiNzNiMDRlYmE3ZTlkOGRhZDRkZTJmYjNlNzFm
10
- MjNjMmM2ZWQ0ZmZiNTZiNzIzNTkxM2VlNDIyMmIyNThmYzQxMzQ1MWZkMjM5
11
- MjRmYWVkMjI5MzRhMDgxZWI4YmY5ZWU3OGI3MjIyOTVlZDA4MWE=
12
- data.tar.gz: !binary |-
13
- YmY2OTZmZmQ1ODJkZDc5ZTFhMDc4YzM2YzY2MTA2ZjMwYzNjZGFkMjVlOGFi
14
- NTA2YWM0YWEyM2ZkY2Q5NzBiN2EyYTliNzAwZWIyMjc3OGJiZjdkNmMyMTE0
15
- YWEzYmRhNTMwMTI5Yjg4NzMxYTk1Mjk2MGNkNTljZjkxZDQzMDM=
2
+ SHA1:
3
+ metadata.gz: 263a54780311ead337a8a6fa7af294972a71cce2
4
+ data.tar.gz: d024e138047f87c0b32fe67734f16aad97b30e5c
5
+ SHA512:
6
+ metadata.gz: f9da4cce5e4d769b51ac5cfed7798c676a42e2061b45774c78400195071eaf07b0615e9196d524b6916aedeef407ddcdfc63b573c38781f3e61bf041ba710d07
7
+ data.tar.gz: af57dea93b88002ca38f8d1ee2d666dc455c6375030eaa53695cdfa6af8ee91bd49b0f96164e7e6945c0dab32020f5eabba2475dbe9bda5434a0950c695af797
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
- #Spfy ("spiffy")
1
+ # Spfy ("spiffy")
2
2
 
3
- ##Overview
3
+ ## Overview
4
4
  **Spfy** is a command-line tool for generating [XSPF](http://xspf.org/) playlists from metadata stored in several popular audio formats and is developed entirely in [Ruby](http://www.ruby-lang.org/). It takes one or more local directory paths as input, extracts metadata tags from any audio files that it encounters, and generates a valid XSPF playlist.
5
5
 
6
- ##Prerequisites
6
+ ## Prerequisites
7
7
  A working Ruby installation (version 1.9 or greater) is required for Spfy to work, but this is outside the scope of this guide. For more information refer to the [official installation procedure](http://www.ruby-lang.org/en/downloads/).
8
8
 
9
9
  [TagLib](http://developer.kde.org/~wheeler/taglib.html) is also required. Follow the steps below (taken from the [taglib-ruby installation guide](http://robinst.github.com/taglib-ruby/)) to install the necessary files for your respective system type:
@@ -15,12 +15,12 @@ A working Ruby installation (version 1.9 or greater) is required for Spfy to wor
15
15
  | Brew | `brew install taglib` |
16
16
  | MacPorts | `sudo port install taglib` |
17
17
 
18
- ##Installation
18
+ ## Installation
19
19
  With the prerequisites above taken care of Spfy can be installed with the following command:
20
20
 
21
21
  $ gem install spfy
22
22
 
23
- ##Using Spfy
23
+ ## Using Spfy
24
24
  By default, Spfy will output a formatted XSPF playlist to the standard output stream that will include _location_, _title_, _creator_, _album_, and _trackNum_ elements for each audio file where available.
25
25
 
26
26
  The general syntax for Spfy is `spfy [options] dir1 ... dirN`, where _dir1 ... dirN_ is one or more paths to directories containing audio files.
@@ -31,19 +31,21 @@ For example:
31
31
 
32
32
  ..will produce the following output (where ~/music contains one audio file with valid metadata):
33
33
 
34
- <?xml version="1.0" encoding="UTF-8"?>
35
- <playlist version="1" xmlns="http://xspf.org/ns/0/">
36
- <trackList>
37
- <track>
38
- <location>file:///Users/spfy/music/03%20A%20Stitch%20In%20Time.mp3</location>
39
- <title>A Stitch In Time</title>
40
- <creator>The Smashing Pumpkins</creator>
41
- <album>Teargarden by Kaleidyscope</album>
42
- <trackNum>3</trackNum>
43
- </track>
44
- </trackList>
45
- </playlist>
46
-
34
+ ```xml
35
+ <?xml version="1.0" encoding="UTF-8"?>
36
+ <playlist version="1" xmlns="http://xspf.org/ns/0/">
37
+ <trackList>
38
+ <track>
39
+ <location>file:///Users/spfy/music/03%20A%20Stitch%20In%20Time.mp3</location>
40
+ <title>A Stitch In Time</title>
41
+ <creator>The Smashing Pumpkins</creator>
42
+ <album>Teargarden by Kaleidyscope</album>
43
+ <trackNum>3</trackNum>
44
+ </track>
45
+ </trackList>
46
+ </playlist>
47
+ ```
48
+
47
49
  Spfy supports multiple directory paths (e.g. `spfy /dir1 /dir2`) and traverses each directory recursively by default. Unsupported files and empty directories in a directory tree are silently ignored and will not impact Spfy's output.
48
50
 
49
51
  Command-line arguments allow you to control which elements Spfy outputs:
@@ -56,13 +58,13 @@ Command-line arguments allow you to control which elements Spfy outputs:
56
58
 
57
59
  For additional options use `spfy --help`.
58
60
 
59
- ##License
61
+ ## License
60
62
  Spfy is free software, and you are welcome to redistribute it under certain conditions. See the [GNU General Public License](http://www.gnu.org/licenses/gpl.html) for more details.
61
63
 
62
- ##Acknowledgments
64
+ ## Acknowledgments
63
65
  Spfy uses the following third party software components:
64
66
 
65
67
  * [taglib-ruby](http://robinst.github.com/taglib-ruby/) by Robin Stocker
66
68
 
67
- ##Comments or suggestions?
68
- Email me at [marc.ransome@fidgetbox.co.uk](marc.ransome@fidgetbox.co.uk) with bug reports, feature requests or general comments and follow [@marcransome](http://www.twitter.com/marcransome) for updates.
69
+ ## Comments or suggestions?
70
+ Email me at [marc.ransome@fidgetbox.co.uk](mailto://marc.ransome@fidgetbox.co.uk) with bug reports, feature requests or general comments and follow [@marcransome](http://www.twitter.com/marcransome) for updates.
data/bin/spfy CHANGED
@@ -2,4 +2,5 @@
2
2
 
3
3
  require 'spfy'
4
4
 
5
- Spfy.generate
5
+ Spfy.parse_args
6
+ Spfy.generate_xml
data/lib/spfy.rb CHANGED
@@ -23,208 +23,115 @@ require "spfy/optionreader"
23
23
  require "optparse"
24
24
  require "ostruct"
25
25
  require "taglib"
26
- require 'find'
27
- require 'uri'
26
+ require "find"
27
+ require "uri"
28
28
 
29
- # The main Spfy class
30
29
  class Spfy
31
-
32
- VERSION = "0.2.2"
30
+
31
+ VERSION = "1.0.0"
32
+ USAGE = "Use `#{File.basename($0)} --help` for available options."
33
+
34
+ @xspf_tags = {
35
+ :header => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"\
36
+ "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n"\
37
+ "\t<trackList>\n",
38
+ :footer => "\t</trackList>\n</playlist>\n",
39
+ :title_start => "\t\t\t<title>",
40
+ :title_end => "</title>\n",
41
+ :creator_start => "\t\t\t<creator>",
42
+ :creator_end => "</creator>\n",
43
+ :album_start => "\t\t\t<album>",
44
+ :album_end => "</album>\n",
45
+ :location_start => "\t\t\t<location>file://",
46
+ :location_end => "</location>\n",
47
+ :track_start => "\t\t<track>\n",
48
+ :track_end => "\t\t</track>\n",
49
+ :track_num_start => "\t\t\t<trackNum>",
50
+ :track_num_end => "</trackNum>\n"
51
+ }
52
+
53
+ def self.parse_args
54
+ begin
55
+ # test for zero arguments
56
+ if ARGV.empty? then
57
+ self.exit_with_banner
58
+ end
59
+
60
+ # parse command-line arguments
61
+ @options = OptionReader.parse(ARGV)
62
+
63
+ # test for zero source paths
64
+ if @options.dirs.empty?
65
+ exit_with_message("No source path(s) specified.")
66
+ end
67
+
68
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => error
69
+ exit_with_message(error.to_s.capitalize)
70
+ end
71
+ end
72
+
73
+ def self.generate_xml
33
74
 
34
- ##
35
- # Starts the XSPF generator.
36
- #
37
- def self.generate
75
+ if @options.output.any?
76
+ puts "Generating XML..."
77
+ self.capture_stdout
78
+ end
79
+
80
+ puts @xspf_tags[:header]
81
+ tracks_processed = 0
82
+
83
+ @options.dirs.each do |dir|
84
+ begin
85
+ Find.find(dir) do |path|
86
+ TagLib::FileRef.open(path) do |fileref|
87
+ tag = fileref.tag
88
+
89
+ next if tag.nil? # skip files with no tags
90
+
91
+ puts "#{@xspf_tags[:track_start]}"
92
+
93
+ if !@options.hide_location
94
+ encoded_path = URI.escape(path).sub("%5C", "/") # percent encode string for local path
95
+ puts "#{@xspf_tags[:location_start]}#{encoded_path}#{@xspf_tags[:location_end]}"
96
+ end
97
+
98
+ puts "#{@xspf_tags[:title_start]}#{tag.title}#{@xspf_tags[:title_end]}" if !@options.hide_title and !tag.title.nil?
99
+ puts "#{@xspf_tags[:creator_start]}#{tag.artist}#{@xspf_tags[:creator_end]}" if !@options.hide_artist and !tag.artist.nil?
100
+ puts "#{@xspf_tags[:album_start]}#{tag.album}#{@xspf_tags[:album_end]}" if !@options.hide_album and !tag.album.nil?
101
+
102
+ if !@options.hide_tracknum and !tag.track.nil?
103
+ if tag.track > 0
104
+ puts "#{@xspf_tags[:track_num_start]}#{tag.track}#{@xspf_tags[:track_num_end]}"
105
+ end
106
+ end
107
+
108
+ puts "#{@xspf_tags[:track_end]}"
109
+
110
+ tracks_processed += 1
111
+ break if @options.tracks_to_process[0].to_i > 0 and tracks_processed == options.tracks_to_process[0].to_i
112
+ end
113
+ end
114
+ rescue Interrupt
115
+ abort("\nCancelled, exiting..")
116
+ end
117
+ end
118
+ puts @xspf_tags[:footer]
119
+
120
+ $stdout = STDOUT if @options.output.any?
121
+ end
38
122
 
39
- # start processing command line arguments
40
- begin
41
-
42
- # short usage banner
43
- simple_usage = "Use `#{File.basename($0)} --help` for available options."
44
-
45
- # test for zero arguments
46
- if ARGV.empty? then
47
- puts simple_usage
48
- exit
49
- end
50
-
51
- # parse command-line arguments
52
- options = OptionReader.parse(ARGV)
53
-
54
- # dirs for traversing
55
- dirs = options.dirs
56
-
57
- # test for zero source paths
58
- if dirs.empty?
59
- puts "No source path specified."
60
- puts simple_usage
61
- exit
62
- end
63
-
64
- rescue OptionParser::InvalidOption => t
65
- puts t
66
- puts simple_usage
67
- exit
68
- rescue OptionParser::MissingArgument => m
69
- puts m
70
- puts simple_usage
71
- exit
72
- end
73
-
74
- # start processing source paths
75
- if options.output.any?
76
- # source path(s) provided, output should be to disk
77
-
78
- # open output file for writing
79
- begin
80
- xmlFile = File.open(options.output[0], "w")
81
- rescue
82
- puts "Unable to open output file for writing."
83
- puts simple_usage
84
- exit
85
- end
86
-
87
- print "Generating XML.."
88
-
89
- # write XSPF header
90
- xmlFile.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
91
- xmlFile.write("<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n")
92
- xmlFile.write("\t<trackList>\n")
93
-
94
- # track count for track limit option
95
- tracks_processed = 0
96
-
97
- # repeat for each source dir argument
98
- dirs.each do |dir|
99
-
100
- begin
101
-
102
- # repeat for each file recursively
103
- Find.find(dir) do |path|
104
-
105
- TagLib::FileRef.open(path) do |fileref|
106
-
107
- tag = fileref.tag
108
-
109
- # skip files with no tags
110
- next if tag.nil?
111
-
112
- # write track metadata
113
- xmlFile.write("\t\t<track>\n")
114
-
115
- if !options.hide_location
116
- # generate a percent encoded string from the local path
117
- encoded_path = URI.escape(path).sub("%5C", "/")
118
- xmlFile.write("\t\t\t<location>file://#{encoded_path}</location>\n")
119
- end
120
-
121
- xmlFile.write("\t\t\t<title>#{tag.title}</title>\n") if !options.hide_title and !tag.title.nil?
122
- xmlFile.write("\t\t\t<creator>#{tag.artist}</creator>\n") if !options.hide_artist and !tag.artist.nil?
123
- xmlFile.write("\t\t\t<album>#{tag.album}</album>\n") if !options.hide_album and !tag.album.nil?
124
-
125
- if !options.hide_tracknum and !tag.track.nil?
126
- if tag.track > 0
127
- xmlFile.write("\t\t\t<trackNum>#{tag.track}</trackNum>\n")
128
- end
129
- end
130
-
131
- xmlFile.write("\t\t</track>\n")
132
-
133
- # increment our track processed count
134
- tracks_processed += 1
135
-
136
- # if a maximum number track numbe has been set, test whether we have reached the limit
137
- if options.tracks_to_process[0].to_i > 0 and tracks_processed == options.tracks_to_process[0].to_i
138
- # write XSPF footer
139
- xmlFile.write("\t</trackList>\n")
140
- xmlFile.write("</playlist>\n")
141
- xmlFile.close
142
- print " success\n"
143
- exit
144
- end
145
- end
146
- end
147
- rescue Interrupt
148
- abort("\nCancelled, exiting..")
149
- end # begin
150
- end # dirs.each do |dir|
151
-
152
- # write XSPF footer
153
- xmlFile.write("\t</trackList>\n")
154
- xmlFile.write("</playlist>\n")
155
-
156
- xmlFile.close
157
-
158
- print " success\n"
159
-
160
- else
161
- # no source path(s) provided, output to stdout
162
-
163
- # write XSPF header
164
- puts "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
165
- puts "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\">\n"
166
- puts "\t<trackList>\n"
167
-
168
- # track count for track limit option
169
- tracks_processed = 0
170
-
171
- # repeat for each source dir argument
172
- dirs.each do |dir|
173
-
174
- begin
175
-
176
- # repeat for each file recursively
177
- Find.find(dir) do |path|
178
-
179
- TagLib::FileRef.open(path) do |fileref|
180
-
181
- tag = fileref.tag
182
-
183
- # skip files with no tags
184
- next if tag.nil?
185
-
186
- # output track metadata
187
- puts "\t\t<track>\n"
188
-
189
- if !options.hide_location
190
- encoded_path = URI.escape(path).sub("%5C", "/")
191
- puts "\t\t\t<location>file://#{encoded_path}</location>\n"
192
- end
193
-
194
- puts "\t\t\t<title>#{tag.title}</title>\n" if !options.hide_title and !tag.title.nil?
195
- puts "\t\t\t<creator>#{tag.artist}</creator>\n" if !options.hide_artist and !tag.artist.nil?
196
- puts "\t\t\t<album>#{tag.album}</album>\n" if !options.hide_album and !tag.album.nil?
197
-
198
- if !options.hide_tracknum and !tag.track.nil?
199
- if tag.track > 0
200
- puts "\t\t\t<trackNum>#{tag.track}</trackNum>\n"
201
- end
202
- end
203
-
204
- puts "\t\t</track>\n"
205
-
206
- # increment our track processed count
207
- tracks_processed += 1
208
-
209
- # if a maximum number track numbe has been set, test whether we have reached the limit
210
- if options.tracks_to_process[0].to_i > 0 and tracks_processed == options.tracks_to_process[0].to_i
211
- # output XSPF footer
212
- puts "\t</trackList>\n"
213
- puts "</playlist>\n"
214
- exit
215
- end
216
- end
217
- end
218
- rescue Interrupt
219
- abort("\nCancelled, exiting..")
220
- end # begin
221
- end # dirs.each do |dir|
222
-
223
- # write XSPF footer
224
- puts "\t</trackList>\n"
225
- puts "</playlist>\n"
226
- end
227
-
228
- end # def self.generate
229
-
230
- end # class Spyf
123
+ def self.exit_with_message(message)
124
+ puts message if message
125
+ exit_with_banner
126
+ end
127
+
128
+ def self.exit_with_banner
129
+ puts USAGE
130
+ exit
131
+ end
132
+
133
+ def self.capture_stdout
134
+ $stdout = File.open(@options.output[0], "w")
135
+ end
136
+
137
+ end
data/spfy.gemspec CHANGED
@@ -20,16 +20,16 @@
20
20
  # along with Spfy. If not, see <http://www.gnu.org/licenses/>.
21
21
 
22
22
  Gem::Specification.new do |s|
23
- s.name = 'spfy'
24
- s.version = '0.2.2'
25
- s.date = '2013-02-26'
26
- s.summary = 'XSPF playlist generator'
27
- s.description = 'Spfy is a simple command-line tool for generating XSPF playlists from metadata stored in several popular audio formats.'
28
- s.authors = ["Marc Ransome"]
29
- s.email = 'marc.ransome@fidgetbox.co.uk'
30
- s.files = `git ls-files`.split("\n")
31
- s.executables << 'spfy'
32
- s.add_runtime_dependency 'taglib-ruby', '>= 0.5.0'
33
- s.homepage = 'http://marcransome.github.com/spfy'
34
- s.license = 'GPL-3'
23
+ s.name = 'spfy'
24
+ s.version = '0.3.0'
25
+ s.date = '2013-07-28'
26
+ s.summary = 'XSPF playlist generator'
27
+ s.description = 'Spfy is a simple command-line tool for generating XSPF playlists from metadata stored in several popular audio formats.'
28
+ s.authors = ["Marc Ransome"]
29
+ s.email = 'marc.ransome@fidgetbox.co.uk'
30
+ s.files = `git ls-files`.split("\n")
31
+ s.executables << 'spfy'
32
+ s.add_runtime_dependency 'taglib-ruby', '>= 0.5.0'
33
+ s.homepage = 'http://marcransome.github.com/spfy'
34
+ s.license = 'GPL-3'
35
35
  end
data/test.sh ADDED
@@ -0,0 +1,36 @@
1
+ #!/bin/bash
2
+ #
3
+ # test.sh
4
+ # Spfy ("spiffy")
5
+ #
6
+ # Copyright (c) 2012, Marc Ransome <marc.ransome@fidgetbox.co.uk>
7
+ #
8
+ # This file is part of Spfy.
9
+ #
10
+ # Spfy is free software: you can redistribute it and/or modify
11
+ # it under the terms of the GNU General Public License as published by
12
+ # the Free Software Foundation, either version 3 of the License, or
13
+ # (at your option) any later version.
14
+ #
15
+ # Spfy is distributed in the hope that it will be useful,
16
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ # GNU General Public License for more details.
19
+ #
20
+ # You should have received a copy of the GNU General Public License
21
+ # along with Spfy. If not, see <http://www.gnu.org/licenses/>.
22
+
23
+ version_from_gemspec=$( grep 's.version' spfy.gemspec | cut -c 16-20 )
24
+ gem_file="spfy-$version_from_gemspec.gem"
25
+
26
+ echo "Removing outdated gem files.."
27
+ rm *.gem
28
+
29
+ echo "Uninstalling previous versions.."
30
+ gem uninstall -a -x spfy
31
+
32
+ echo "Building gem.."
33
+ gem build spfy.gemspec
34
+
35
+ echo "Installing gem file.."
36
+ gem install $gem_file
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spfy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc Ransome
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-02-26 00:00:00.000000000 Z
11
+ date: 2013-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: taglib-ruby
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.5.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.5.0
27
27
  description: Spfy is a simple command-line tool for generating XSPF playlists from
@@ -38,6 +38,7 @@ files:
38
38
  - lib/spfy.rb
39
39
  - lib/spfy/optionreader.rb
40
40
  - spfy.gemspec
41
+ - test.sh
41
42
  homepage: http://marcransome.github.com/spfy
42
43
  licenses:
43
44
  - GPL-3
@@ -48,17 +49,17 @@ require_paths:
48
49
  - lib
49
50
  required_ruby_version: !ruby/object:Gem::Requirement
50
51
  requirements:
51
- - - ! '>='
52
+ - - '>='
52
53
  - !ruby/object:Gem::Version
53
54
  version: '0'
54
55
  required_rubygems_version: !ruby/object:Gem::Requirement
55
56
  requirements:
56
- - - ! '>='
57
+ - - '>='
57
58
  - !ruby/object:Gem::Version
58
59
  version: '0'
59
60
  requirements: []
60
61
  rubyforge_project:
61
- rubygems_version: 2.0.0
62
+ rubygems_version: 2.0.6
62
63
  signing_key:
63
64
  specification_version: 4
64
65
  summary: XSPF playlist generator