traktor-nml 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +81 -30
- data/lib/traktor/nml.rb +9 -9
- data/lib/traktor/nml/collection.rb +32 -6
- data/lib/traktor/nml/cue.rb +20 -0
- data/lib/traktor/nml/file.rb +18 -0
- data/lib/traktor/nml/playlist.rb +19 -0
- data/lib/traktor/nml/track.rb +30 -0
- data/lib/traktor/nml/version.rb +1 -1
- data/spec/traktor/nml_spec.rb +37 -3
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a975f0344949062aa901da4cfb09178e10877377
|
4
|
+
data.tar.gz: 325b02f803405a3a7dc7015a0b5f4c79cd09d1bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 213163283d378e4d088ff1ce248323590e50c0c9de164bcc723b9b66f2477ac97023a9b032069a8aa203bd14cc57e4f6589a8c57124c0965dd28adfb354b6f50
|
7
|
+
data.tar.gz: a18161acdadb9157f9e89a1bfde78c6ec1c16f2b987f425aa2643347b375bfe7cc96ebe8f14a43042fd414dee4d994dc5d9c05042c4fb6cc8a4966e756eddd43
|
data/README.md
CHANGED
@@ -27,44 +27,95 @@ Or install it yourself as:
|
|
27
27
|
require 'traktor/nml'
|
28
28
|
|
29
29
|
Traktor::NML.parse File.open("path/to/playlist.nml")
|
30
|
+
Traktor::NML.load "path/to/playlist.nml"
|
30
31
|
# or
|
31
32
|
Traktor::NML.parse content_of_nml
|
32
33
|
```
|
33
34
|
|
34
35
|
`Traktor::NML.parse` will return array of hash like this:
|
35
36
|
|
36
|
-
```
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
:
|
65
|
-
|
37
|
+
```irb
|
38
|
+
irb(main):001:0> require 'traktor/nml'
|
39
|
+
=> true
|
40
|
+
irb(main):002:0> Traktor::NML.parse(File.read(File.expand_path "./spec/traktor/traktor-nml-demo.nml"))
|
41
|
+
=> #<Traktor::NML::Playlist:0x007f8f3bbdd270 @tracks=[
|
42
|
+
#<Traktor::NML::Track:0x007f8f3bbfc058
|
43
|
+
@title="Green Night Parade (PandaBoY Remix)",
|
44
|
+
@artist="fu_mou",
|
45
|
+
@album={:title=>"Green Night Parade EP", :track=>"6"},
|
46
|
+
@primarykey="G:/:Music/:fu_mou/:Green Night Parade EP/:06 Green Night Parade (PandaBoY Remi.mp3",
|
47
|
+
@genre="ALTEMA Records",
|
48
|
+
@label="",
|
49
|
+
@release_date="2011/1/1",
|
50
|
+
@playtime=371.0,
|
51
|
+
@bpm=131.999,
|
52
|
+
@key="3d",
|
53
|
+
@musical_key="2",
|
54
|
+
@cues=[
|
55
|
+
#<Traktor::NML::Cue:0x007f8f3bbfeb28 @name="n.n.", @type=0, @start=483.713, @length=0.0, @repeats=-1, @hotcue=0>,
|
56
|
+
#<Traktor::NML::Cue:0x007f8f3bbfe538 @name="n.n.", @type=4, @start=4119.93, @length=0.0, @repeats=-1, @hotcue=1>,
|
57
|
+
#<Traktor::NML::Cue:0x007f8f3bbfdf48 @name="n.n.", @type=0, @start=33211.1, @length=0.0, @repeats=-1, @hotcue=2>,
|
58
|
+
#<Traktor::NML::Cue:0x007f8f3bbfd958 @name="n.n.", @type=0, @start=47756.6, @length=0.0, @repeats=-1, @hotcue=3>,
|
59
|
+
#<Traktor::NML::Cue:0x007f8f3bbfd340 @name="n.n.", @type=0, @start=76847.6, @length=0.0, @repeats=-1, @hotcue=4>,
|
60
|
+
#<Traktor::NML::Cue:0x007f8f3bbfcd00 @name="n.n.", @type=0, @start=91393.2, @length=0.0, @repeats=-1, @hotcue=5>,
|
61
|
+
#<Traktor::NML::Cue:0x007f8f3bbfc6c0 @name="n.n.", @type=0, @start=120484.0,@length=0.0, @repeats=-1, @hotcue=6>,
|
62
|
+
#<Traktor::NML::Cue:0x007f8f3bbfc0a8 @name="n.n.", @type=0, @start=149576.0, @length=0.0, @repeats=-1, @hotcue=7>
|
63
|
+
]
|
64
|
+
>,
|
65
|
+
#<Traktor::NML::Track:0x007f8f3bc14dd8
|
66
|
+
@title="Sweet Tear(Y calla K Cut Electro Remix)",
|
67
|
+
@artist="Calla Soiled",
|
68
|
+
@album={:title=>"Sweet Tear EP", :track=>"2"},
|
69
|
+
@primarykey="G:/:Music/:Calla Soiled/:Sweet Tear EP/:02 Sweet Tear(Y calla K Cut Electro.mp3",
|
70
|
+
@genre="ALTEMA Records",
|
71
|
+
@label="",
|
72
|
+
@release_date="2010/1/1",
|
73
|
+
@playtime=320.0,
|
74
|
+
@bpm=132.0,
|
75
|
+
@key="12d",
|
76
|
+
@musical_key="5",
|
77
|
+
@cues=[
|
78
|
+
#<Traktor::NML::Cue:0x007f8f3bc74b48 @name="n.n.", @type=0, @start=26.5843, @length=0.0, @repeats=-1, @hotcue=0>,
|
79
|
+
#<Traktor::NML::Cue:0x007f8f3bc74558 @name="n.n.", @type=4, @start=3666.41, @length=0.0, @repeats=-1, @hotcue=1>,
|
80
|
+
#<Traktor::NML::Cue:0x007f8f3bc17e98 @name="n.n.", @type=0, @start=18208.4, @length=0.0, @repeats=-1, @hotcue=2>,
|
81
|
+
#<Traktor::NML::Cue:0x007f8f3bc17330 @name="n.n.", @type=0, @start=32753.9, @length=0.0, @repeats=-1, @hotcue=3>,
|
82
|
+
#<Traktor::NML::Cue:0x007f8f3bc167c8 @name="n.n.", @type=0, @start=47299.3, @length=0.0, @repeats=-1, @hotcue=4>,
|
83
|
+
#<Traktor::NML::Cue:0x007f8f3bc15cb0 @name="n.n.", @type=0, @start=90935.7, @length=0.0, @repeats=-1, @hotcue=5>,
|
84
|
+
#<Traktor::NML::Cue:0x007f8f3bc15468 @name="n.n.", @type=0, @start=120027.0, @length=0.0, @repeats=-1, @hotcue=6>,
|
85
|
+
#<Traktor::NML::Cue:0x007f8f3bc14e28 @name="n.n.", @type=0, @start=149117.0, @length=0.0, @repeats=-1, @hotcue=7>
|
86
|
+
]
|
87
|
+
>,
|
88
|
+
#<Traktor::NML::Track:0x007f8f3bbde620
|
89
|
+
@title="もしも星屑が泣いたとして",
|
90
|
+
@artist="Calla Soiled",
|
91
|
+
@album={:title=>"Dirty Nucleus", :track=>"7"},
|
92
|
+
@primarykey="G:/:Music/:Calla Soiled/:Dirty Nucleus/:07 もしも星屑が泣いたとして.mp3",
|
93
|
+
@genre="",
|
94
|
+
@label="",
|
95
|
+
@release_date="2010/1/1",
|
96
|
+
@playtime=362.0,
|
97
|
+
@bpm=139.005,
|
98
|
+
@key="11m",
|
99
|
+
@musical_key="19",
|
100
|
+
@cues=[
|
101
|
+
#<Traktor::NML::Cue:0x007f8f3bbe5948 @name="Beat Marker", @type=4, @start=434.042, @length=0.0, @repeats=-1, @hotcue=-1>,
|
102
|
+
#<Traktor::NML::Cue:0x007f8f3bbe52e0 @name="n.n.", @type=4, @start=434.042, @length=0.0, @repeats=-1, @hotcue=0>,
|
103
|
+
#<Traktor::NML::Cue:0x007f8f3bbe4bd8 @name="n.n.", @type=0, @start=14246.2, @length=0.0, @repeats=-1, @hotcue=1>,
|
104
|
+
#<Traktor::NML::Cue:0x007f8f3bbe4520 @name="n.n.", @type=0, @start=28058.7, @length=0.0, @repeats=-1, @hotcue=2>,
|
105
|
+
#<Traktor::NML::Cue:0x007f8f3bbdfe80 @name="n.n.", @type=0, @start=41871.4, @length=0.0, @repeats=-1, @hotcue=3>,
|
106
|
+
#<Traktor::NML::Cue:0x007f8f3bbdf840 @name="n.n.", @type=0, @start=55683.6, @length=0.0, @repeats=-1, @hotcue=4>,
|
107
|
+
#<Traktor::NML::Cue:0x007f8f3bbdf250 @name="n.n.", @type=0, @start=83308.5, @length=0.0, @repeats=-1, @hotcue=5>,
|
108
|
+
#<Traktor::NML::Cue:0x007f8f3bbdec60 @name="n.n.", @type=0, @start=97121.0, @length=0.0, @repeats=-1, @hotcue=6>,
|
109
|
+
#<Traktor::NML::Cue:0x007f8f3bbde670 @name="n.n.", @type=0, @start=124746.0,@length=0.0, @repeats=-1, @hotcue=7>
|
110
|
+
]
|
111
|
+
>
|
112
|
+
]>
|
66
113
|
```
|
67
114
|
|
115
|
+
## Notice
|
116
|
+
|
117
|
+
* Release date may be like `YYYY/1/1` when only YEAR is specified in file
|
118
|
+
|
68
119
|
## Contributing
|
69
120
|
|
70
121
|
1. Fork it ( https://github.com/polamjag/traktor-nml/fork )
|
data/lib/traktor/nml.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
require "traktor/nml/
|
2
|
-
require "traktor/nml/playlist"
|
3
|
-
require "traktor/nml/version"
|
4
|
-
require "oga"
|
1
|
+
require "traktor/nml/file"
|
5
2
|
|
6
3
|
module Traktor
|
7
4
|
module NML
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
class << self
|
6
|
+
def parse(content)
|
7
|
+
Traktor::NML::File.new(content).playlist
|
8
|
+
end
|
9
|
+
|
10
|
+
def load(filepath)
|
11
|
+
Traktor::NML::File.new(::File.read filepath).playlist
|
12
|
+
end
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -1,13 +1,18 @@
|
|
1
1
|
require "oga"
|
2
|
+
require "date"
|
3
|
+
require "traktor/nml/track"
|
4
|
+
require "traktor/nml/cue"
|
2
5
|
|
3
6
|
module Traktor
|
4
7
|
module NML
|
5
8
|
class Collection
|
9
|
+
include Enumerable
|
10
|
+
|
6
11
|
attr_reader :collection
|
7
12
|
|
8
13
|
def initialize(node)
|
9
14
|
@collection = node.map do |el|
|
10
|
-
{
|
15
|
+
Traktor::NML::Track.new({
|
11
16
|
title: try_text(el.attribute('TITLE')),
|
12
17
|
artist: try_text(el.attribute('ARTIST')),
|
13
18
|
album: {
|
@@ -20,30 +25,47 @@ module Traktor
|
|
20
25
|
genre: el.xpath('INFO[@GENRE]').attribute('GENRE').map{ |e| e.text }.join(", "),
|
21
26
|
label: el.xpath('INFO[@LABEL]').attribute('LABEL').map{ |e| e.text }.join(", "),
|
22
27
|
playtime: el.xpath('INFO[@PLAYTIME]').attribute('PLAYTIME').map{ |e| e.text.to_f }.first,
|
23
|
-
release_date: el.xpath('INFO[@RELEASE_DATE]').attribute('RELEASE_DATE').map{ |e| e.text }.join(", "),
|
28
|
+
release_date: parse_date(el.xpath('INFO[@RELEASE_DATE]').attribute('RELEASE_DATE').map{ |e| e.text }.join(", ")),
|
24
29
|
bpm: el.xpath('TEMPO[@BPM]').attribute('BPM').map{ |e| e.text.to_f }.first,
|
25
30
|
key: try_text(el.xpath('INFO[@KEY]').attribute('KEY').first),
|
26
31
|
musical_key: try_text(el.xpath('MUSICAL_KEY[@VALUE]').attribute('VALUE').first),
|
27
32
|
cues: el.xpath('CUE_V2').map do |cue|
|
28
|
-
{
|
33
|
+
Traktor::NML::Cue.new({
|
29
34
|
name: cue.attribute('NAME').value,
|
30
35
|
type: cue.attribute('TYPE').value.to_i,
|
31
36
|
start: cue.attribute('START').value.to_f,
|
32
37
|
length: cue.attribute('LEN').value.to_f,
|
33
38
|
repeats: cue.attribute('REPEATS').value.to_i,
|
34
39
|
hotcue: cue.attribute('HOTCUE').value.to_i
|
35
|
-
}
|
40
|
+
})
|
36
41
|
end
|
37
|
-
}
|
42
|
+
})
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
41
46
|
def track_from_primarykey(primarykey)
|
42
47
|
@collection.select do |track|
|
43
|
-
track
|
48
|
+
track.primarykey == primarykey
|
44
49
|
end.first
|
45
50
|
end
|
46
51
|
|
52
|
+
def length
|
53
|
+
@collection.length
|
54
|
+
end
|
55
|
+
alias_method :size, :length
|
56
|
+
|
57
|
+
def each
|
58
|
+
@collection.each do |track|
|
59
|
+
yield track
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def [](i)
|
64
|
+
@collection[i]
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
private
|
47
69
|
def try_text(elm)
|
48
70
|
if elm.nil?
|
49
71
|
""
|
@@ -51,6 +73,10 @@ module Traktor
|
|
51
73
|
elm.text
|
52
74
|
end
|
53
75
|
end
|
76
|
+
|
77
|
+
def parse_date(date)
|
78
|
+
Date.parse date unless date.empty?
|
79
|
+
end
|
54
80
|
end
|
55
81
|
end
|
56
82
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Traktor
|
2
|
+
module NML
|
3
|
+
class Cue
|
4
|
+
attr_reader :name, :type, :start, :length, :repeats, :hotcue
|
5
|
+
|
6
|
+
def initialize(info)
|
7
|
+
@name = info[:name]
|
8
|
+
@type = info[:type]
|
9
|
+
@start = info[:start]
|
10
|
+
@length = info[:length]
|
11
|
+
@repeats = info[:repeats]
|
12
|
+
@hotcue = info[:hotcue]
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
return self.instance_variable_get("@#{key.to_s}")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "oga"
|
2
|
+
require "traktor/nml/collection"
|
3
|
+
require "traktor/nml/playlist"
|
4
|
+
|
5
|
+
module Traktor
|
6
|
+
module NML
|
7
|
+
class File
|
8
|
+
attr_reader :collection, :playlist
|
9
|
+
|
10
|
+
def initialize(content)
|
11
|
+
doc = Oga.parse_xml content
|
12
|
+
|
13
|
+
@collection = Traktor::NML::Collection.new doc.xpath('NML/COLLECTION/ENTRY')
|
14
|
+
@playlist = Traktor::NML::Playlist.new doc.xpath('NML/PLAYLISTS'), @collection
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/traktor/nml/playlist.rb
CHANGED
@@ -3,13 +3,32 @@ require "oga"
|
|
3
3
|
module Traktor
|
4
4
|
module NML
|
5
5
|
class Playlist
|
6
|
+
include Enumerable
|
7
|
+
|
6
8
|
attr_reader :tracks
|
9
|
+
|
7
10
|
def initialize(node, collection)
|
8
11
|
@tracks = (find_playlist node).first.xpath('PLAYLIST/ENTRY/PRIMARYKEY').map do |track|
|
9
12
|
collection.track_from_primarykey track.attribute('KEY').text
|
10
13
|
end.compact
|
11
14
|
end
|
12
15
|
|
16
|
+
def length
|
17
|
+
@tracks.length
|
18
|
+
end
|
19
|
+
alias_method :size, :length
|
20
|
+
|
21
|
+
def each
|
22
|
+
@tracks.each do |track|
|
23
|
+
yield track
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](i)
|
28
|
+
@tracks[i]
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
13
32
|
def find_playlist(node)
|
14
33
|
node.each do |nd|
|
15
34
|
nd.xpath('NODE/SUBNODES').each do |elm|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Traktor
|
2
|
+
module NML
|
3
|
+
class Track
|
4
|
+
attr_reader :title, :artist, :album,
|
5
|
+
:primarykey,
|
6
|
+
:genre, :label, :release_date,
|
7
|
+
:playtime, :bpm, :key, :musical_key,
|
8
|
+
:cues
|
9
|
+
|
10
|
+
def initialize(info)
|
11
|
+
@title = info[:title]
|
12
|
+
@artist = info[:artist]
|
13
|
+
@album = info[:album]
|
14
|
+
@primarykey = info[:primarykey]
|
15
|
+
@genre = info[:genre]
|
16
|
+
@label = info[:label]
|
17
|
+
@release_date = info[:release_date]
|
18
|
+
@playtime = info[:playtime]
|
19
|
+
@bpm = info[:bpm]
|
20
|
+
@key = info[:key]
|
21
|
+
@musical_key = info[:musical_key]
|
22
|
+
@cues = info[:cues]
|
23
|
+
end
|
24
|
+
|
25
|
+
def [](key)
|
26
|
+
return self.instance_variable_get("@#{key.to_s}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/traktor/nml/version.rb
CHANGED
data/spec/traktor/nml_spec.rb
CHANGED
@@ -1,17 +1,51 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Traktor::NML do
|
4
|
+
before do
|
5
|
+
@path_nml_win = (File.join File.dirname(__FILE__), "win.nml")
|
6
|
+
@path_nml_win_embedded = (File.join File.dirname(__FILE__), "win_in_folder.nml")
|
7
|
+
@path_nml_osx = (File.join File.dirname(__FILE__), "osx.nml")
|
8
|
+
end
|
9
|
+
|
4
10
|
it 'has a version number' do
|
5
11
|
expect(Traktor::NML::VERSION).not_to be nil
|
6
12
|
end
|
7
13
|
|
8
14
|
it 'can parse nml file ver 18' do
|
9
|
-
expect((Traktor::NML.parse File.open
|
15
|
+
expect((Traktor::NML.parse File.open @path_nml_win).length).to eq(40)
|
10
16
|
end
|
11
17
|
it 'can parse nml file ver 18, playlist is in directory' do
|
12
|
-
expect((Traktor::NML.parse File.open
|
18
|
+
expect((Traktor::NML.parse File.open @path_nml_win_embedded).length).to eq(43)
|
13
19
|
end
|
14
20
|
it 'can parse nml file of OSX, ver 16' do
|
15
|
-
expect((Traktor::NML.parse File.open
|
21
|
+
expect((Traktor::NML.parse File.open @path_nml_osx).length).to eq(34)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Traktor::NML::Playlist do
|
25
|
+
before do
|
26
|
+
@playlist = Traktor::NML.load @path_nml_win
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'has length' do
|
30
|
+
expect(@playlist.length).to eq 40
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'is Enumerable' do
|
34
|
+
expect(@playlist.map{|pl| pl.title }.length).to eq 40
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe Traktor::NML::Collection do
|
39
|
+
before do
|
40
|
+
@file = Traktor::NML::File.new ::File.read @path_nml_win
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'has length' do
|
44
|
+
expect(@file.collection.length).to eq 40
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'is Enumerable' do
|
48
|
+
expect(@file.collection.map{|pl| pl.title }.length).to eq 40
|
49
|
+
end
|
16
50
|
end
|
17
51
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: traktor-nml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- polamjag
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oga
|
@@ -97,7 +97,10 @@ files:
|
|
97
97
|
- circle.yml
|
98
98
|
- lib/traktor/nml.rb
|
99
99
|
- lib/traktor/nml/collection.rb
|
100
|
+
- lib/traktor/nml/cue.rb
|
101
|
+
- lib/traktor/nml/file.rb
|
100
102
|
- lib/traktor/nml/playlist.rb
|
103
|
+
- lib/traktor/nml/track.rb
|
101
104
|
- lib/traktor/nml/version.rb
|
102
105
|
- spec/spec_helper.rb
|
103
106
|
- spec/traktor/nml_spec.rb
|