playlist 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 30be0088143707327ec29c8888bd04f94ee2ff22
4
- data.tar.gz: 1c462de277427d226a81ce130c060910ac74c525
2
+ SHA256:
3
+ metadata.gz: 81dea6b42315190f6066d99551de62d84752aacf44fb39721fbea24e6713c4e3
4
+ data.tar.gz: b7e528d0db40b684efab812c09a7dcf566b44d468f058035037094c84f99bb1f
5
5
  SHA512:
6
- metadata.gz: 53b751fa9ad238e6acb13c0287e84ec4387a86d406d3a6ade773eb2bad5d1571b656328ac336a6cd5f24932ed4e609be4dd283cac437b57200293d290ebd54cc
7
- data.tar.gz: 21563296d9604407988d425bc9002b830bee0be57c118982ffa32408fefc0e04e87de29d506be7a7e85b560cdefc4cdc66143a6969173bbc74b036ced80c841a
6
+ metadata.gz: f6b9a2047b4bd0093b2f22053a2a8ac247a711fa5abffbfc838aed9b884e2011eb156ba88f65d28da7f4f1e9446807d8f2b422b75cbb4a42c846a530e1fcaf43
7
+ data.tar.gz: '019d2491fdac856319d36ceb3941d83eac7139a5679970b8fd8de51da384ddff8eb3941655f1b0d5c1eb3dd90489290ce601b3047b8dfcd4de1b07852abad7d0'
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.0
2
+ TargetRubyVersion: 2.3
3
3
  Exclude:
4
4
  - 'vendor/**/*'
5
5
 
@@ -12,17 +12,28 @@ Style/HashSyntax:
12
12
  Style/MutableConstant:
13
13
  Enabled: false
14
14
 
15
+ Style/FrozenStringLiteralComment:
16
+ Enabled: false
17
+
15
18
  Style/SymbolArray:
16
19
  EnforcedStyle: brackets
17
20
 
18
21
  Style/ClassAndModuleChildren:
19
22
  EnforcedStyle: compact
20
23
 
21
- MethodLength:
24
+ # Not available in older rubies
25
+ Style/SafeNavigation:
26
+ Enabled: false
27
+
28
+ # Disabled because it makes the code longer, more repetitive
29
+ Style/FormatStringToken:
30
+ Enabled: false
31
+
32
+ Metrics/MethodLength:
22
33
  Max: 20
23
34
 
24
35
  Metrics/AbcSize:
25
- Max: 20
36
+ Max: 25
26
37
 
27
38
  # Allow long blocks in rspec
28
39
  Metrics/BlockLength:
@@ -2,4 +2,4 @@ sudo: false
2
2
  language: ruby
3
3
  rvm:
4
4
  - 2.2.2
5
- before_install: gem install bundler -v 1.13.7
5
+ - 2.5.2
data/README.md CHANGED
@@ -7,8 +7,10 @@ This ruby gem allows you to create and manipulate playlists of musical tracks.
7
7
  It supports parsing and generating playlists in the following formats:
8
8
 
9
9
  * M3U
10
+ * PLS
10
11
  * XSPF
11
12
  * A simple human readable format
13
+ * Cue Sheet
12
14
 
13
15
  ## Installation
14
16
 
@@ -27,6 +27,10 @@ class Playlist
27
27
  # @return [String]
28
28
  attr_accessor :license
29
29
 
30
+ # URI of an image associated with this playlist
31
+ # @return [String]
32
+ attr_accessor :image
33
+
30
34
  # Get a hash of identifier for this playlist
31
35
  # Identifiers can either be Strings or URIs
32
36
  # @return [Hash] an hash of identifiers
@@ -68,6 +72,7 @@ class Playlist
68
72
  time = tracks.first.start_time || 0
69
73
  tracks.each do |track|
70
74
  break if track.duration.nil?
75
+
71
76
  time = (track.start_time ||= time)
72
77
  time += track.duration
73
78
  end
@@ -2,6 +2,7 @@
2
2
  module Playlist::Format
3
3
  autoload :Cue, 'playlist/format/cue'
4
4
  autoload :M3U, 'playlist/format/m3u'
5
+ autoload :PLS, 'playlist/format/pls'
5
6
  autoload :SimpleText, 'playlist/format/simple_text'
6
7
  autoload :XSPF, 'playlist/format/xspf'
7
8
  end
@@ -0,0 +1,91 @@
1
+ # Module to parse and generate PLS playlists
2
+ module Playlist::Format::PLS
3
+ class << self
4
+ # Parse a PLS file into a [Playlist]
5
+ # @param input any object that responds to #each_line
6
+ # (either a String or a IO object)
7
+ # @return [Playlist] a new Playlist object
8
+ def parse(input)
9
+ tracks = parse_lines_to_array(input)
10
+
11
+ # Now convert to objects
12
+ array_to_object(tracks)
13
+ end
14
+
15
+ # Generate a PLS file from a [Playlist]
16
+ # @param playlist [Playlist] the playlist to be converted to PLS
17
+ # @return [String] PLS as a string
18
+ def generate(playlist)
19
+ text = "[playlist]\n\n"
20
+ playlist.tracks.each_with_index do |t, index|
21
+ index += 1
22
+ duration = (t.duration / 1000).round
23
+ text += "File#{index}=#{t.location}\n"
24
+ if t.creator && t.title
25
+ text += "Title#{index}=#{t.creator} - #{t.title}\n"
26
+ elsif t.title
27
+ text += "Title#{index}=#{t.title}\n"
28
+ end
29
+ text += "Length#{index}=#{duration}\n"
30
+ text += "\n"
31
+ end
32
+ text += "NumberOfEntries=#{playlist.tracks.count}\n"
33
+ text += "Version=2\n"
34
+ text
35
+ end
36
+
37
+ protected
38
+
39
+ def parse_line(tracks, line)
40
+ if (matches = line.match(/^([a-z]+)(\d+)=(.+)$/i))
41
+ key = matches[1].downcase.to_sym
42
+ num = matches[2].to_i - 1
43
+ tracks[num] ||= {}
44
+ tracks[num][key] = matches[3]
45
+ elsif (matches = line.match(/^NumberOfEntries=(\d+)$/))
46
+ if matches[1].to_i != tracks.count
47
+ raise 'PLS parse error: NumberOfEntries is incorrect'
48
+ end
49
+ elsif (matches = line.match(/^Version=(\d+)$/))
50
+ if matches[1] != '2'
51
+ raise "PLS file version #{version} is not supported"
52
+ end
53
+ else
54
+ warn "Unable to parse line: #{line}"
55
+ end
56
+ end
57
+
58
+ def parse_lines_to_array(input)
59
+ tracks = []
60
+ input.each_line.with_index do |line, index|
61
+ line.strip!
62
+ if index.zero?
63
+ if line == '[playlist]'
64
+ next
65
+ else
66
+ raise 'PLS parse error: first line is not [playlist]'
67
+ end
68
+ end
69
+ parse_line(tracks, line) unless line.empty?
70
+ end
71
+ tracks
72
+ end
73
+
74
+ def array_to_object(tracks)
75
+ Playlist.new do |playlist|
76
+ tracks.each do |track|
77
+ obj = Playlist::Track.new
78
+ obj.location = track[:file] unless track[:file].nil?
79
+ obj.duration = track[:length].to_i * 1000 unless track[:length].nil?
80
+ if (matches = track[:title].match(/^(.+) - (.+)$/))
81
+ obj.creator = matches[1]
82
+ obj.title = matches[2]
83
+ else
84
+ obj.title = track[:title]
85
+ end
86
+ playlist.add_track(obj)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -14,9 +14,12 @@ module Playlist::Format::XSPF
14
14
  Playlist.new do |playlist|
15
15
  doc = Nokogiri::XML(input)
16
16
  playlist.title = doc.content_at('/xmlns:playlist/xmlns:title')
17
+ playlist.creator = doc.content_at('/xmlns:playlist/xmlns:creator')
17
18
  playlist.description = doc.content_at(
18
19
  '/xmlns:playlist/xmlns:annotation'
19
20
  )
21
+ playlist.image = doc.content_at('/xmlns:playlist/xmlns:image')
22
+ playlist.info_url = doc.content_at('/xmlns:playlist/xmlns:info')
20
23
  doc.xpath('/xmlns:playlist/xmlns:trackList/xmlns:track').each do |track|
21
24
  playlist.tracks << parse_track(track)
22
25
  end
@@ -29,8 +32,14 @@ module Playlist::Format::XSPF
29
32
  def generate(playlist)
30
33
  builder = Nokogiri::XML::Builder.new do |xml|
31
34
  xml.playlist(:version => 1, :xmlns => 'http://xspf.org/ns/0/') do
32
- xml.title(playlist.title) unless playlist.title.nil?
33
- xml.annotation(playlist.description) unless playlist.description.nil?
35
+ build_xml_unless_nil(
36
+ xml,
37
+ :title => playlist.title,
38
+ :creator => playlist.creator,
39
+ :annotation => playlist.description,
40
+ :image => playlist.image,
41
+ :info => playlist.info_url
42
+ )
34
43
  xml.trackList do
35
44
  playlist.tracks.each { |track| generate_track(xml, track) }
36
45
  end
@@ -43,21 +52,36 @@ module Playlist::Format::XSPF
43
52
 
44
53
  def parse_track(doc)
45
54
  Playlist::Track.new do |track|
46
- track.creator = doc.content_at('./xmlns:creator')
47
- track.title = doc.content_at('./xmlns:title')
48
55
  track.location = doc.content_at('./xmlns:location')
56
+ track.title = doc.content_at('./xmlns:title')
57
+ track.creator = doc.content_at('./xmlns:creator')
49
58
  if (duration = doc.content_at('./xmlns:duration'))
50
59
  track.duration = duration.to_i
51
60
  end
61
+ track.album = doc.content_at('./xmlns:album')
62
+ track.description = doc.content_at('./xmlns:annotation')
63
+ track.image = doc.content_at('./xmlns:image')
52
64
  end
53
65
  end
54
66
 
55
67
  def generate_track(xml, track)
56
68
  xml.track do
57
- xml.location(track.location) unless track.location.nil?
58
- xml.title(track.title) unless track.title.nil?
59
- xml.creator(track.creator) unless track.creator.nil?
60
- xml.duration(track.duration) unless track.duration.nil?
69
+ build_xml_unless_nil(
70
+ xml,
71
+ :location => track.location,
72
+ :title => track.title,
73
+ :creator => track.creator,
74
+ :duration => track.duration,
75
+ :album => track.album,
76
+ :annotation => track.description,
77
+ :image => track.image
78
+ )
79
+ end
80
+ end
81
+
82
+ def build_xml_unless_nil(xml, hash)
83
+ hash.each_pair do |key, value|
84
+ xml.send(key, value) unless value.nil?
61
85
  end
62
86
  end
63
87
  end
@@ -11,6 +11,10 @@ class Playlist::Track
11
11
  # @return [String]
12
12
  attr_accessor :album
13
13
 
14
+ # A description/annotation/synopsis of the track
15
+ # @return [String]
16
+ attr_accessor :description
17
+
14
18
  # The catalogue number of the album that the track came from
15
19
  # Also known as the UPC/EAN code
16
20
  # @return [String]
@@ -51,6 +55,10 @@ class Playlist::Track
51
55
  # @return [Array<Contributor>] an array of tracks in the playlist
52
56
  attr_reader :contributors
53
57
 
58
+ # URI of an image associated with this Track
59
+ # @return [String]
60
+ attr_accessor :image
61
+
54
62
  # Create a new Track
55
63
  # @param attr [Hash] a hash of attibute values to set
56
64
  def initialize(attr = {})
@@ -1,4 +1,4 @@
1
1
  class Playlist
2
2
  # The version number of the Playlist Ruby gem
3
- VERSION = '1.1.0'
3
+ VERSION = '1.2.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: playlist
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicholas Humfrey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-03 00:00:00.000000000 Z
11
+ date: 2020-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -142,6 +142,7 @@ files:
142
142
  - lib/playlist/format.rb
143
143
  - lib/playlist/format/cue.rb
144
144
  - lib/playlist/format/m3u.rb
145
+ - lib/playlist/format/pls.rb
145
146
  - lib/playlist/format/simple_text.rb
146
147
  - lib/playlist/format/xspf.rb
147
148
  - lib/playlist/track.rb
@@ -167,7 +168,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
168
  version: '0'
168
169
  requirements: []
169
170
  rubyforge_project:
170
- rubygems_version: 2.4.5
171
+ rubygems_version: 2.7.6.2
171
172
  signing_key:
172
173
  specification_version: 4
173
174
  summary: Convert playlists between different formats