walkman 0.1.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/lib/walkman.rb +57 -0
- data/lib/walkman/cli.rb +128 -0
- data/lib/walkman/commands/controls.rb +33 -0
- data/lib/walkman/commands/information.rb +26 -0
- data/lib/walkman/commands/player.rb +15 -0
- data/lib/walkman/commands/playlist.rb +17 -0
- data/lib/walkman/commands/queueing.rb +31 -0
- data/lib/walkman/config.rb +94 -0
- data/lib/walkman/player.rb +105 -0
- data/lib/walkman/playlist.rb +139 -0
- data/lib/walkman/services/base.rb +25 -0
- data/lib/walkman/services/rdio.rb +64 -0
- data/lib/walkman/services/rdio/rdio_player.rb +85 -0
- data/lib/walkman/song.rb +11 -0
- data/spec/factories/echowrap.rb +79 -0
- data/spec/factories/playlist.rb +32 -0
- data/spec/factories/song.rb +13 -0
- data/spec/sinatra_helper.rb +12 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/walkman/commands/controls_spec.rb +26 -0
- data/spec/walkman/commands/information_spec.rb +45 -0
- data/spec/walkman/commands/player_spec.rb +19 -0
- data/spec/walkman/commands/queueing_spec.rb +62 -0
- data/spec/walkman/player_spec.rb +102 -0
- data/spec/walkman/playlist_spec.rb +150 -0
- data/spec/walkman/services/base_spec.rb +13 -0
- data/spec/walkman/services/rdio/rdio_player_spec.rb +24 -0
- data/spec/walkman/services/rdio_spec.rb +70 -0
- data/spec/walkman/song_spec.rb +33 -0
- data/walkman.gemspec +29 -0
- metadata +222 -0
data/lib/walkman/song.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :echowrap_track, class: Echowrap::Track do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
ignore do
|
6
|
+
catalog { "rdio-US" }
|
7
|
+
duration { 300 }
|
8
|
+
foreign_id { "rdio-US:track:t12345678" }
|
9
|
+
foreign_release_id { "rdio-US:release:a123456" }
|
10
|
+
id { "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890" }
|
11
|
+
end
|
12
|
+
|
13
|
+
initialize_with do
|
14
|
+
Echowrap::Track.new(
|
15
|
+
catalog: catalog,
|
16
|
+
duration: duration,
|
17
|
+
foreign_id: foreign_id,
|
18
|
+
foreign_release_id: foreign_release_id,
|
19
|
+
id: id
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
factory :echowrap_song, class: Echowrap::Song do
|
25
|
+
skip_create
|
26
|
+
|
27
|
+
ignore do
|
28
|
+
artist_name { "Artist" }
|
29
|
+
artist_foreign_ids { [{ catalog: "rdio-US", foreign_id: "rdio-US:artist:r12345" }] }
|
30
|
+
title { "Title" }
|
31
|
+
tracks { [create(:echowrap_track)] }
|
32
|
+
end
|
33
|
+
|
34
|
+
initialize_with do
|
35
|
+
song = Echowrap::Song.new(
|
36
|
+
artist_name: artist_name,
|
37
|
+
artist_foreign_ids: artist_foreign_ids,
|
38
|
+
title: title
|
39
|
+
)
|
40
|
+
|
41
|
+
[tracks].flatten.each { |track| song.tracks << track }
|
42
|
+
song
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
factory :echowrap_playlist, class: Echowrap::Playlist do
|
47
|
+
skip_create
|
48
|
+
|
49
|
+
ignore do
|
50
|
+
code 0
|
51
|
+
message { "Success" }
|
52
|
+
version "4.2"
|
53
|
+
session_id { "ABCDEFG123456789" }
|
54
|
+
lookahead { [] }
|
55
|
+
songs { [create(:echowrap_song)] }
|
56
|
+
end
|
57
|
+
|
58
|
+
trait :dynamic_create do
|
59
|
+
initialize_with do
|
60
|
+
Echowrap::Playlist.new(
|
61
|
+
status: { version: version, code: code, message: message },
|
62
|
+
session_id: session_id
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
trait :dynamic_next do
|
68
|
+
initialize_with do
|
69
|
+
playlist = Echowrap::Playlist.new(
|
70
|
+
status: { version: version, code: code, message: message },
|
71
|
+
lookahead: lookahead,
|
72
|
+
)
|
73
|
+
|
74
|
+
[songs].flatten.each { |song| playlist.songs << song }
|
75
|
+
playlist
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :playlist, class: Walkman::Playlist do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
ignore do
|
6
|
+
artist { "Artist" }
|
7
|
+
auto_queue { false }
|
8
|
+
session_id { "ABCDEFG123456789" }
|
9
|
+
songs { [] }
|
10
|
+
type { "artist" }
|
11
|
+
end
|
12
|
+
|
13
|
+
initialize_with do
|
14
|
+
Walkman::Playlist.new(
|
15
|
+
session_id: session_id,
|
16
|
+
songs: songs
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
trait :dynamic_artist do
|
21
|
+
initialize_with do
|
22
|
+
Walkman::Playlist.new(
|
23
|
+
artist: artist,
|
24
|
+
auto_queue: auto_queue,
|
25
|
+
session_id: session_id,
|
26
|
+
songs: songs,
|
27
|
+
type: type
|
28
|
+
)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :song, class: Walkman::Song do
|
3
|
+
skip_create
|
4
|
+
|
5
|
+
sequence(:album) { |x| "Album#{x}" }
|
6
|
+
sequence(:artist) { |x| "Artist#{x}" }
|
7
|
+
sequence(:echonest_artist_id) { |x| "ARTISTID#{x}" }
|
8
|
+
sequence(:echonest_song_id) { |x| "SONGID#{x}" }
|
9
|
+
sequence(:source_id) { |x| "t#{x}" }
|
10
|
+
source_type { Walkman::Player::SERVICES.shuffle.first.to_s }
|
11
|
+
sequence(:title) { |x| "Title#{x}" }
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Commands::Controls do
|
4
|
+
let!(:player) { Walkman.player }
|
5
|
+
|
6
|
+
describe ".play" do
|
7
|
+
it "calls play on the player" do
|
8
|
+
expect(player).to receive(:play)
|
9
|
+
Walkman::Commands::Controls.play
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".stop" do
|
14
|
+
it "calls stop on the player" do
|
15
|
+
expect(player).to receive(:stop)
|
16
|
+
Walkman::Commands::Controls.stop
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe ".next" do
|
21
|
+
it "calls next on the player" do
|
22
|
+
expect(player).to receive(:next)
|
23
|
+
Walkman::Commands::Controls.next
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Commands::Information do
|
4
|
+
let(:player) { Walkman.player }
|
5
|
+
let(:song) { Walkman::Song.new(title: "Bar", artist: "Foo", album: "Baz") }
|
6
|
+
|
7
|
+
describe ".now_playing" do
|
8
|
+
it "returns track info about the current song if playing" do
|
9
|
+
player.current_song = song
|
10
|
+
|
11
|
+
expect(Walkman::Commands::Information.now_playing).to include("Now playing")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns a notice if no song is playing" do
|
15
|
+
player.current_song = nil
|
16
|
+
|
17
|
+
expect(Walkman::Commands::Information.now_playing).to eq("No music is playing")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".up_next" do
|
22
|
+
before :each do
|
23
|
+
player.playlist = Walkman::Playlist.new
|
24
|
+
5.times { player.playlist.add(song) }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "shows the next 5 songs in the playlist" do
|
28
|
+
expect(Walkman::Commands::Information.up_next).to eq(
|
29
|
+
"Foo - Bar\n" +
|
30
|
+
"Foo - Bar\n" +
|
31
|
+
"Foo - Bar\n" +
|
32
|
+
"Foo - Bar\n" +
|
33
|
+
"Foo - Bar\n"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "shows the specified number of songs in the playlist" do
|
38
|
+
expect(Walkman::Commands::Information.up_next(3)).to eq(
|
39
|
+
"Foo - Bar\n" +
|
40
|
+
"Foo - Bar\n" +
|
41
|
+
"Foo - Bar\n"
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Commands::Player do
|
4
|
+
let!(:player) { Walkman.player }
|
5
|
+
|
6
|
+
describe ".start" do
|
7
|
+
it "calls startup on the player" do
|
8
|
+
expect(player).to receive(:startup)
|
9
|
+
Walkman::Commands::Player.start
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".stop" do
|
14
|
+
it "calls shutdown on the player" do
|
15
|
+
expect(player).to receive(:shutdown)
|
16
|
+
Walkman::Commands::Player.stop
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Commands::Queueing do
|
4
|
+
let!(:player) { Walkman.player }
|
5
|
+
let!(:song) { create(:echowrap_song, artist_name: "Artist") }
|
6
|
+
let!(:playlist_dynamic_create) { create(:echowrap_playlist, :dynamic_create) }
|
7
|
+
let!(:playlist_dynamic_next) { create(:echowrap_playlist, :dynamic_next, songs: [song]) }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
player.playlist = nil
|
11
|
+
player.current_song = nil
|
12
|
+
|
13
|
+
Walkman.echowrap.stub(:playlist_dynamic_create) { playlist_dynamic_create }
|
14
|
+
Walkman.echowrap.stub(:playlist_dynamic_next) { playlist_dynamic_next }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe ".artist" do
|
18
|
+
it "queries echo nest for the songs by the given artist" do
|
19
|
+
expect(Walkman.echowrap).to receive(:playlist_dynamic_create)
|
20
|
+
expect(Walkman.echowrap).to receive(:playlist_dynamic_next)
|
21
|
+
|
22
|
+
expect {
|
23
|
+
Walkman::Commands::Queueing.artist("Artist") # from stub
|
24
|
+
}.to change {
|
25
|
+
player.playlist.size
|
26
|
+
}.from(0).to(1)
|
27
|
+
|
28
|
+
expect(player.playlist.instance_variable_get("@session_id")).to eq(playlist_dynamic_create.session_id)
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "songs found on echo nest" do
|
32
|
+
it "adds songs to the current playlist" do
|
33
|
+
expect {
|
34
|
+
Walkman::Commands::Queueing.artist("Artist") # from stub
|
35
|
+
}.to change {
|
36
|
+
player.playlist.size
|
37
|
+
}.from(0).to(1)
|
38
|
+
|
39
|
+
expect(player.current_song.artist).to eq(song.artist_name)
|
40
|
+
expect(player.current_song.title).to eq(song.title)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "no songs found on echo nest" do
|
45
|
+
it "displays information about the failed search" do
|
46
|
+
playlist_dynamic_next = create(:echowrap_playlist, :dynamic_next, songs: [])
|
47
|
+
Walkman.echowrap.stub(:playlist_dynamic_next) { playlist_dynamic_next }
|
48
|
+
|
49
|
+
expect(player.playlist.size).to eq(0)
|
50
|
+
expect(Walkman::Commands::Queueing.artist("Foo")).to eq("That artist couldn't be queued")
|
51
|
+
expect(player.playlist.size).to be(0)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".play_song"
|
57
|
+
describe ".play_album_by_artist"
|
58
|
+
describe ".play_song_by_artist"
|
59
|
+
|
60
|
+
describe ".play_like_artist"
|
61
|
+
describe ".play_like_song_by_artist"
|
62
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Player do
|
4
|
+
let!(:player) { Walkman.player }
|
5
|
+
|
6
|
+
after :each do
|
7
|
+
player.shutdown
|
8
|
+
player.playlist = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "responds to #playlist" do
|
12
|
+
expect(player).to respond_to(:playlist)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#services" do
|
16
|
+
it "returns a hash of all services this player knows about" do
|
17
|
+
expect(player.services.keys).to include("Walkman::Services::Rdio")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#startup" do
|
22
|
+
it "starts up all music services" do
|
23
|
+
Walkman::Player::SERVICES.each do |service|
|
24
|
+
service.any_instance.stub(:startup)
|
25
|
+
expect_any_instance_of(service).to receive(:startup)
|
26
|
+
end
|
27
|
+
|
28
|
+
player.startup
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#shutdown" do
|
33
|
+
it "shuts down all music services" do
|
34
|
+
Walkman::Player::SERVICES.each do |service|
|
35
|
+
service.any_instance.stub(:shutdown)
|
36
|
+
expect_any_instance_of(service).to receive(:shutdown)
|
37
|
+
end
|
38
|
+
|
39
|
+
player.shutdown
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#play" do
|
44
|
+
it "plays a song from a specific music service" do
|
45
|
+
player.startup
|
46
|
+
|
47
|
+
Walkman::Player::SERVICES.each do |service|
|
48
|
+
service.any_instance.stub(:play)
|
49
|
+
player.current_song = create(:song, source_type: service.name)
|
50
|
+
expect_any_instance_of(service).to receive(:play)
|
51
|
+
end
|
52
|
+
|
53
|
+
player.play
|
54
|
+
|
55
|
+
sleep 0.2 # have to give the play loop a chance to pick up the song
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "#stop" do
|
60
|
+
it "stops all music services" do
|
61
|
+
Walkman::Player::SERVICES.each do |service|
|
62
|
+
service.any_instance.stub(:stop)
|
63
|
+
expect_any_instance_of(service).to receive(:stop)
|
64
|
+
end
|
65
|
+
|
66
|
+
player.stop
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#next" do
|
71
|
+
let!(:song) { create(:song) }
|
72
|
+
let!(:playlist) { create(:playlist) }
|
73
|
+
|
74
|
+
before do
|
75
|
+
player.startup
|
76
|
+
player.playlist = playlist
|
77
|
+
end
|
78
|
+
|
79
|
+
it "plays the next song in the playlist" do
|
80
|
+
player.playlist.clear
|
81
|
+
player.playlist.add(song)
|
82
|
+
player.current_song = nil
|
83
|
+
|
84
|
+
expect {
|
85
|
+
player.next
|
86
|
+
}.to change {
|
87
|
+
player.current_song
|
88
|
+
}.from(nil).to(song)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "stops playing if there are no more songs in the playlist queue" do
|
92
|
+
player.playlist.clear
|
93
|
+
player.playing = true
|
94
|
+
player.current_song = song
|
95
|
+
|
96
|
+
player.next
|
97
|
+
|
98
|
+
expect(player.current_song).to be_nil
|
99
|
+
expect(player.playing).to be_false
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Walkman::Playlist do
|
4
|
+
let(:playlist) { create(:playlist) }
|
5
|
+
let(:song) { create(:song) }
|
6
|
+
|
7
|
+
it "responds to #session_id" do
|
8
|
+
expect(playlist).to respond_to(:session_id)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe ".new" do
|
12
|
+
it "initializes an empty queue" do
|
13
|
+
expect(playlist.queue).to eq([])
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initializes with a single song" do
|
17
|
+
song_playlist = Walkman::Playlist.new(songs: song)
|
18
|
+
|
19
|
+
expect(song_playlist.queue).to eq([song])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "initializes with a multiple songs" do
|
23
|
+
song2 = create(:song)
|
24
|
+
songs_playlist = Walkman::Playlist.new(songs: [song, song2])
|
25
|
+
|
26
|
+
expect(songs_playlist.queue).to eq([song, song2])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#queue" do
|
31
|
+
it "returns the current queue" do
|
32
|
+
playlist.add(song)
|
33
|
+
|
34
|
+
expect(playlist.queue).to eq([song])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#include?" do
|
39
|
+
it "returns true if the given song is currently queued" do
|
40
|
+
playlist.add(song)
|
41
|
+
|
42
|
+
expect(playlist.include?(song)).to be_true
|
43
|
+
expect(playlist.queued?(song)).to be_true
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns false if the given song is not currently queued" do
|
47
|
+
expect(playlist.include?(song)).to be_false
|
48
|
+
expect(playlist.queued?(song)).to be_false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#clear" do
|
53
|
+
it "empties the current queue" do
|
54
|
+
playlist.add(song)
|
55
|
+
|
56
|
+
expect {
|
57
|
+
playlist.clear
|
58
|
+
}.to change {
|
59
|
+
playlist.queue.count
|
60
|
+
}.from(1).to(0)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe "#add" do
|
65
|
+
it "adds multiple songs to the end of the queue" do
|
66
|
+
songs = []
|
67
|
+
|
68
|
+
3.times do
|
69
|
+
songs << create(:song)
|
70
|
+
end
|
71
|
+
|
72
|
+
expect {
|
73
|
+
playlist.add(songs)
|
74
|
+
}.to change {
|
75
|
+
playlist.queue.size
|
76
|
+
}.from(0).to(3)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "adds a song to the end of the queue" do
|
80
|
+
3.times { playlist.add(create(:song)) }
|
81
|
+
|
82
|
+
expect {
|
83
|
+
playlist.add(song)
|
84
|
+
}.to change {
|
85
|
+
playlist.queue.size
|
86
|
+
}.from(3).to(4)
|
87
|
+
|
88
|
+
expect(playlist.queue.index(song)).to eq(3)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "inserts a song into the given index" do
|
92
|
+
3.times { playlist.add(create(:song)) }
|
93
|
+
|
94
|
+
playlist.add(song, 0)
|
95
|
+
|
96
|
+
expect(playlist.queue.index(song)).to eq(0)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "ignores invalid indexes when adding a song" do
|
100
|
+
3.times { playlist.add(create(:song)) }
|
101
|
+
|
102
|
+
playlist.add(song, 999)
|
103
|
+
|
104
|
+
expect(playlist.queue.index(song)).to eq(3)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#remove" do
|
109
|
+
it "removes the given song from the queue" do
|
110
|
+
playlist.add(song)
|
111
|
+
|
112
|
+
expect {
|
113
|
+
playlist.remove(song)
|
114
|
+
}.to change {
|
115
|
+
playlist.queue.size
|
116
|
+
}.from(1).to(0)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#shuffle" do
|
121
|
+
it "changes the order of songs in the queue" do
|
122
|
+
100.times { playlist.add(create(:song)) }
|
123
|
+
|
124
|
+
expect {
|
125
|
+
playlist.shuffle
|
126
|
+
}.to change {
|
127
|
+
playlist.queue.first
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "#next" do
|
133
|
+
it "returns the next song from the playlist" do
|
134
|
+
song2 = create(:song)
|
135
|
+
|
136
|
+
playlist.add([song, song2])
|
137
|
+
|
138
|
+
expect(playlist.next).to eq(song)
|
139
|
+
expect(playlist.next).to eq(song2)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "#size" do
|
144
|
+
it "returns the size of the playlist queue" do
|
145
|
+
3.times { playlist.add(create(:song)) }
|
146
|
+
|
147
|
+
expect(playlist.size).to eq(3)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|