walkman 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e3d7ee1e1eeb85342fc9df700432e1a1879cf58
4
- data.tar.gz: 7538521e2f9691d497aa9f780279fe6034d995d0
3
+ metadata.gz: 428f899c2b92b174d1e6693ee29932c5a9cd94e9
4
+ data.tar.gz: 5c352d5761efddeddfa5e685dfa4f081845473dc
5
5
  SHA512:
6
- metadata.gz: fb245267ddb8f2c75c0cf3711ee9d4006df6c2deefed5985cabb458d0b0bd38a48d6cce3c04fdca97ab3fa0fa397838cc2d9c14f6c2af7571a3bb657471cb20f
7
- data.tar.gz: 549890eeb0a29f384329909e17d59d71ac0b69060489aad7d19f55a97a0adb0461e74d0b16f8f67a21cf2c7945e3b5e039ee25e2012314d33ad689182b4f7ef9
6
+ metadata.gz: 43891034d99e8453e2dca48a3a839670038ddda1218862e709ab679c4613e15cb3c130e2b767334e07a3f1d1fb52472b776f81abe8effc83fdf37d5b1d67b7a6
7
+ data.tar.gz: ea21f3a6d49a991556b1dc0f1372a9000841ec7bd5ed3272bb859cac67f0803f8770b3e1bb9ec9056a7ce18f4b686bd93005f2655ec565740af3842a3f194aa9
data/README.md CHANGED
@@ -29,7 +29,7 @@ with support for [Spotify](http://spotify.com) and local file playback via
29
29
  3. Create a catalog (taste profile) to use as your base library and grab its `id` to use as `catalog_id`:
30
30
 
31
31
  ```
32
- curl -F "api_key=<api_key>" -F "format=json" -F "type=general" -F "name=base_profile"
32
+ curl -F "api_key=<api_key>" -F "format=json" -F "type=general" -F "name=base_profile" "http://developer.echonest.com/api/v4/tasteprofile/create"
33
33
  ```
34
34
 
35
35
  ### Rdio
@@ -49,4 +49,4 @@ echonest:
49
49
  catalog_id: CACABCD1234567890Z
50
50
  rdio:
51
51
  playback_token: GAlNi78J_____zlyYWs5ZG02N2pkaHlhcWsyOWJtYjkyN2xvY2FsaG9zdEbwl7EHvbylWSWFWYMZwfc=
52
- ```
52
+ ```
data/bin/walkman ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "walkman"
4
+
5
+ Walkman::CLI.start
data/lib/walkman.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "echowrap"
2
2
 
3
3
  require "walkman/config"
4
+ require "walkman/logger"
4
5
 
5
6
  require "walkman/services/base"
6
7
  require "walkman/services/rdio"
@@ -19,34 +20,6 @@ require "walkman/commands/queueing"
19
20
  require "walkman/cli"
20
21
 
21
22
  module Walkman
22
- def self.logger
23
- @@logger ||= ::Logger.new(STDOUT).tap do |l|
24
- l.level = log_level(Walkman.config.log_level)
25
- l.formatter = proc do |severity, _, _, message|
26
- "[walkman](#{severity.downcase}): #{message}\n"
27
- end
28
- end
29
- end
30
-
31
- def self.log_level(log_level_string)
32
- case log_level_string.to_s
33
- when "unknown"
34
- ::Logger::UNKNOWN
35
- when "fatal"
36
- ::Logger::FATAL
37
- when "error"
38
- ::Logger::ERROR
39
- when "warn"
40
- ::Logger::WARN
41
- when "info"
42
- ::Logger::INFO
43
- when "debug"
44
- ::Logger::DEBUG
45
- else
46
- raise "Unknown log level given #{log_level_string}"
47
- end
48
- end
49
-
50
23
  def self.echowrap
51
24
  @echowrap ||= Echowrap.configure do |config|
52
25
  config.api_key = Walkman.config.echonest_api_key
data/lib/walkman/cli.rb CHANGED
@@ -4,14 +4,13 @@ require "colorize"
4
4
 
5
5
  module Walkman
6
6
  class CLI < Thor
7
-
8
7
  # server tasks
9
8
 
10
9
  desc "start", "starts the walkman server"
11
10
  option :daemon, type: :boolean, aliases: "-d"
12
11
  def start
13
12
  if options[:daemon]
14
- Process.daemon
13
+ Process.daemon
15
14
  else
16
15
  puts "Starting walkman server"
17
16
  puts "Run `walkman start -d` for daemon"
@@ -19,11 +18,9 @@ module Walkman
19
18
 
20
19
  trap("INT") do
21
20
  # calling this in a thread to get proper logging
22
- thread = Thread.new do
21
+ Thread.new do
23
22
  shutdown
24
- end
25
-
26
- thread.join
23
+ end.join
27
24
  end
28
25
  end
29
26
 
@@ -58,13 +55,13 @@ module Walkman
58
55
 
59
56
  desc "next", "plays the next song in the current playlist"
60
57
  def next(count = 1)
61
- response = server.run_command(:next, { count: count.to_i })
58
+ response = server.run_command(:next, count: count.to_i)
62
59
  puts response unless response.empty?
63
60
  end
64
61
 
65
62
  desc "skip COUNT", "skips the given amount of songs"
66
63
  def skip(count = 1)
67
- response = server.run_command(:skip, { count: count.to_i })
64
+ response = server.run_command(:skip, count: count.to_i)
68
65
  puts response unless response.empty?
69
66
  end
70
67
 
@@ -83,14 +80,14 @@ module Walkman
83
80
  desc "play_artist ARTIST", "plays songs from the given artist"
84
81
  def play_artist(*artist)
85
82
  artist = artist.join(" ")
86
- response = server.run_command(:artist, { artist: artist })
83
+ response = server.run_command(:artist, artist: artist)
87
84
  puts response unless response.empty?
88
85
  end
89
86
 
90
87
  desc "play_artist_radio ARTIST", "plays music like the given artist"
91
88
  def play_artist_radio(*artist)
92
89
  artist = artist.join(" ")
93
- response = server.run_command(:artist_radio, { artist: artist })
90
+ response = server.run_command(:artist_radio, artist: artist)
94
91
  puts response unless response.empty?
95
92
  end
96
93
 
@@ -17,7 +17,7 @@ module Walkman
17
17
 
18
18
  def self.next(count = 1)
19
19
  if current_song = Walkman.player.current_song
20
- Walkman.player.playlist.skip(current_song)
20
+ Walkman.player.playlist.feedback(:skip, current_song)
21
21
  end
22
22
 
23
23
  Walkman.player.next(count)
@@ -6,12 +6,21 @@ module Walkman
6
6
  playlist = Walkman.player.playlist
7
7
 
8
8
  if current_song && playlist
9
- playlist.favorite(current_song)
9
+ playlist.feedback(:favorite, current_song)
10
10
  "Awesome! I'll play more songs like this."
11
11
  else
12
12
  "No music is playing. Are you hearing things?"
13
13
  end
14
14
  end
15
+
16
+ def self.shuffle!
17
+ if playlist = Walkman.player.playlist
18
+ playlist.shuffle!
19
+ "Shaking things up a bit."
20
+ else
21
+ "No music is queued."
22
+ end
23
+ end
15
24
  end
16
25
  end
17
26
  end
@@ -2,11 +2,9 @@ module Walkman
2
2
  module Commands
3
3
  module Queueing
4
4
  def self.artist(artist)
5
- playlist = Walkman::Playlist.new(type: "artist", artist: artist, auto_queue: true)
6
- Walkman.player.playlist = playlist
5
+ playlist = self.queue("artist", artist: artist)
7
6
 
8
7
  if playlist.size > 0
9
- Walkman.player.next
10
8
  output = ["♫".blue, "Playing songs by", artist.titleize.bold]
11
9
  output.flatten.join(" ")
12
10
  else
@@ -15,17 +13,30 @@ module Walkman
15
13
  end
16
14
 
17
15
  def self.artist_radio(artist)
18
- playlist = Walkman::Playlist.new(type: "artist-radio", artist: artist, auto_queue: true)
19
- Walkman.player.playlist = playlist
16
+ playlist = self.queue("artist-radio", artist: artist)
20
17
 
21
18
  if playlist.size > 0
22
- Walkman.player.next
23
19
  output = ["♫".blue, "Playing music like", artist.titleize.bold]
24
20
  output.flatten.join(" ")
25
21
  else
26
22
  "Music like that artist couldn't be queued"
27
23
  end
28
24
  end
25
+
26
+ private
27
+
28
+ def self.queue(type, args = {})
29
+ args.merge!(type: type.to_s, auto_queue: true)
30
+
31
+ playlist = Walkman::Playlist.new(args)
32
+ Walkman.player.playlist = playlist
33
+
34
+ if playlist.size > 0
35
+ Walkman.player.next
36
+ end
37
+
38
+ playlist
39
+ end
29
40
  end
30
41
  end
31
42
  end
@@ -0,0 +1,27 @@
1
+ module Walkman
2
+ def self.logger
3
+ @@logger ||= ::Logger.new(STDOUT).tap do |l|
4
+ l.level = log_level(Walkman.config.log_level)
5
+ l.formatter = proc do |severity, _, _, message|
6
+ "[walkman](#{severity.downcase}): #{message}\n"
7
+ end
8
+ end
9
+ end
10
+
11
+ def self.log_level(log_level_string)
12
+ case log_level_string.to_s
13
+ when "debug"
14
+ ::Logger::DEBUG
15
+ when "info"
16
+ ::Logger::INFO
17
+ when "warn"
18
+ ::Logger::WARN
19
+ when "error"
20
+ ::Logger::ERROR
21
+ when "fatal"
22
+ ::Logger::FATAL
23
+ else
24
+ raise "Unknown log level given #{log_level_string}"
25
+ end
26
+ end
27
+ end
@@ -5,6 +5,7 @@ module Walkman
5
5
 
6
6
  class Player
7
7
  attr_accessor :current_song, :playing
8
+ attr_writer :playlist
8
9
 
9
10
  SERVICES = [Walkman::Services::Rdio]
10
11
 
@@ -92,10 +93,6 @@ module Walkman
92
93
  @playlist ||= Walkman::Playlist.new
93
94
  end
94
95
 
95
- def playlist=(playlist)
96
- @playlist = playlist
97
- end
98
-
99
96
  private
100
97
 
101
98
  def play_song(song)
@@ -1,6 +1,7 @@
1
1
  module Walkman
2
2
  class Playlist
3
3
  attr_accessor :session_id
4
+ attr_reader :queue
4
5
 
5
6
  def initialize(options = {})
6
7
  songs = options.delete(:songs) || []
@@ -12,14 +13,11 @@ module Walkman
12
13
  end
13
14
 
14
15
  if @auto_queue && @session_id
15
- auto_queue && self.next
16
+ auto_queue
17
+ self.next
16
18
  end
17
19
  end
18
20
 
19
- def queue
20
- @queue
21
- end
22
-
23
21
  def clear
24
22
  @queue = []
25
23
  end
@@ -29,7 +27,7 @@ module Walkman
29
27
  end
30
28
  alias_method :queued?, :include?
31
29
 
32
- def shuffle
30
+ def shuffle!
33
31
  @queue.shuffle!
34
32
  end
35
33
 
@@ -51,7 +49,7 @@ module Walkman
51
49
  song = songs.pop # the last song skipped
52
50
 
53
51
  # skip and unplay songs so our echonest catalog/profile stays true
54
- skip(songs)
52
+ feedback([:skip, :unplay], songs) unless songs.empty?
55
53
 
56
54
  if @auto_queue && size <= 5
57
55
  auto_queue(5) if @session_id
@@ -64,76 +62,65 @@ module Walkman
64
62
  @queue.size
65
63
  end
66
64
 
67
- def unplay(songs)
68
- songs = [songs].flatten # one or more
69
-
70
- songs.each do |song|
71
- echonest_playlist_feedback({ unplay_song: song.echonest_song_id })
72
- end
73
- end
74
-
75
- def skip(songs)
76
- songs = [songs].flatten # one or more
65
+ def feedback(types, songs)
66
+ songs = [songs].flatten # one or more
67
+ types = [types].flatten # one or more
68
+ song_ids = songs.map(&:echonest_song_id)
69
+ args = { session_id: @session_id }
77
70
 
78
- songs.each do |song|
79
- echonest_playlist_feedback({ skip_song: song.echonest_song_id, unplay_song: song.echonest_song_id })
71
+ if types.include?(:favorite)
72
+ args[:favorite_song] = song_ids
73
+ args[:favorite_artist] = songs.map(&:echonest_artist_id)
80
74
  end
81
- end
82
75
 
83
- def favorite(songs)
84
- songs = [songs].flatten # one or more
76
+ args[:unplay_song] = song_ids if types.include?(:unplay)
77
+ args[:skip_song] = song_ids if types.include?(:skip)
85
78
 
86
- songs.each do |song|
87
- echonest_playlist_feedback({ favorite_song: song.echonest_song_id, favorite_artist: song.echonest_artist_id })
88
- end
79
+ Walkman.echowrap.playlist_dynamic_feedback(args)
89
80
  end
90
81
 
91
82
  private
92
83
 
93
- def echonest_playlist_create(options = {})
94
- return nil unless options.keys.include?(:type)
84
+ def echonest_playlist_create(args = {})
85
+ return nil unless args.keys.include?(:type)
95
86
 
96
- options[:bucket] = ["id:rdio-US", "tracks"]
97
- options[:seed_catalog] = Walkman.config.echonest_catalog_id
98
- options[:session_catalog] = Walkman.config.echonest_catalog_id
87
+ args[:bucket] = ["id:rdio-US", "tracks"]
88
+ args[:seed_catalog] = Walkman.config.echonest_catalog_id
89
+ args[:session_catalog] = Walkman.config.echonest_catalog_id
99
90
 
100
- if remote_playlist = Walkman.echowrap.playlist_dynamic_create(options)
91
+ if remote_playlist = Walkman.echowrap.playlist_dynamic_create(args)
101
92
  remote_playlist
102
93
  else
103
94
  nil
104
95
  end
105
96
  end
106
97
 
107
- def echonest_playlist_feedback(args = {})
108
- args[:session_id] = @session_id
109
-
110
- Walkman.echowrap.playlist_dynamic_feedback(args)
111
- end
112
-
113
98
  def auto_queue(count = 5)
114
99
  return 0 unless @session_id
115
100
 
116
101
  result = Walkman.echowrap.playlist_dynamic_next(session_id: @session_id, results: count)
117
- songs = []
102
+ songs = parse_remote_songs(result.songs)
103
+ add(songs)
104
+ end
118
105
 
119
- result.songs.each do |song|
106
+ def parse_remote_songs(remote_songs)
107
+ remote_songs.map do |song|
120
108
  # find the first track with a rdio foreign key
121
109
  track = song.tracks.find do |t|
122
110
  t.foreign_id && t.foreign_id.split(":")[0] == "rdio-US"
123
111
  end
124
112
 
125
- next unless track
126
-
127
- songs << Walkman::Song.new(artist: song.artist_name,
128
- title: song.title,
129
- source_type: "Walkman::Services::Rdio",
130
- source_id: track.foreign_id.split(":").last,
131
- echonest_artist_id: song.artist_id,
132
- echonest_song_id: song.id)
133
- end
134
-
135
- add(songs)
136
- songs.count
113
+ if track
114
+ Walkman::Song.new(artist: song.artist_name,
115
+ title: song.title,
116
+ source_type: "Walkman::Services::Rdio",
117
+ source_id: track.foreign_id.split(":").last,
118
+ echonest_artist_id: song.artist_id,
119
+ echonest_song_id: song.id)
120
+ else
121
+ nil
122
+ end
123
+ end.compact # prune any nil elements
137
124
  end
138
125
  end
139
126
  end
@@ -2,23 +2,23 @@ module Walkman
2
2
  module Services
3
3
  class Base
4
4
  def startup
5
- raise("Implement in Service")
5
+ raise "Implement in Service"
6
6
  end
7
7
 
8
8
  def shutdown
9
- raise("Implement in Service")
9
+ raise "Implement in Service"
10
10
  end
11
11
 
12
12
  def restart
13
- raise("Implement in Service")
13
+ raise "Implement in Service"
14
14
  end
15
15
 
16
16
  def play(song)
17
- raise("Implement in Service")
17
+ raise "Implement in Service"
18
18
  end
19
19
 
20
20
  def stop
21
- raise("Implement in Service")
21
+ raise "Implement in Service"
22
22
  end
23
23
  end
24
24
  end
@@ -12,6 +12,7 @@ module Walkman
12
12
  def shutdown
13
13
  Walkman.logger.debug "stopping Rdio service"
14
14
 
15
+ quit_browser
15
16
  @player_thread.terminate if @player_thread
16
17
  end
17
18
 
@@ -0,0 +1,13 @@
1
+ log_level: info
2
+ server:
3
+ host: localhost
4
+ port: 27001
5
+ echonest:
6
+ api_key: ABC
7
+ consumer_key: DEF
8
+ shared_secret: GHI
9
+ catalog_id: JKL
10
+ rdio:
11
+ playback_token: MNO
12
+ player_url: http://localhost:1/rdio
13
+ browser_path: /path/to/browser
data/spec/spec_helper.rb CHANGED
@@ -7,4 +7,11 @@ require "walkman"
7
7
 
8
8
  Dir[File.expand_path("../support/*.rb", __FILE__)].each { |f| require f }
9
9
 
10
- Walkman.logger.level = Walkman.log_level(:info)
10
+ Walkman.config.log_level = :info
11
+
12
+ before do
13
+ Walkman.echowrap.stub(:playlist_dynamic_create)
14
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
15
+ Walkman.echowrap.stub(:playlist_dynamic_next)
16
+ Command.stub(:run)
17
+ end
@@ -0,0 +1,5 @@
1
+ RSpec.configure do |config|
2
+ config.mock_with :rspec do |c|
3
+ c.syntax = [:should, :expect]
4
+ end
5
+ end
@@ -3,6 +3,10 @@ require "spec_helper"
3
3
  describe Walkman::Commands::Controls do
4
4
  let!(:player) { Walkman.player }
5
5
 
6
+ before do
7
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
8
+ end
9
+
6
10
  describe ".play" do
7
11
  it "calls play on the player" do
8
12
  expect(player).to receive(:play)
@@ -22,5 +26,24 @@ describe Walkman::Commands::Controls do
22
26
  expect(player).to receive(:next)
23
27
  Walkman::Commands::Controls.next
24
28
  end
29
+
30
+ it "updates the current song's skip count" do
31
+ song = create(:song)
32
+ player.current_song = song
33
+ player.playlist = create(:playlist)
34
+
35
+ expect(player.playlist).to receive(:feedback).with(:skip, song).once
36
+
37
+ Walkman::Commands::Controls.next
38
+ end
39
+
40
+ it "updates the skipped songs' skip count" do
41
+ songs = create_list(:song, 3)
42
+ player.playlist = create(:playlist, songs: songs)
43
+
44
+ expect(player.playlist).to receive(:feedback).with([:skip, :unplay], songs.take(2)).once
45
+
46
+ Walkman::Commands::Controls.skip(3)
47
+ end
25
48
  end
26
49
  end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Walkman::Commands::Playlist do
4
+ let!(:player) { Walkman.player }
5
+ let!(:playlist) { Walkman::Playlist.new }
6
+
7
+ before do
8
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
9
+ end
10
+
11
+ describe ".like" do
12
+ it "updates the song's like count" do
13
+ player.playlist = playlist
14
+ song = create(:song)
15
+ player.current_song = song
16
+
17
+ expect(player.playlist).to receive(:feedback).with(:favorite, song)
18
+
19
+ expect(Walkman::Commands::Playlist.like).to eq("Awesome! I'll play more songs like this.")
20
+ end
21
+
22
+ it "returns a notification if there is not a current song" do
23
+ player.current_song = nil
24
+
25
+ expect(Walkman::Commands::Playlist.like).to eq("No music is playing. Are you hearing things?")
26
+ end
27
+ end
28
+ end
@@ -12,6 +12,7 @@ describe Walkman::Commands::Queueing do
12
12
 
13
13
  Walkman.echowrap.stub(:playlist_dynamic_create) { playlist_dynamic_create }
14
14
  Walkman.echowrap.stub(:playlist_dynamic_next) { playlist_dynamic_next }
15
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
15
16
  end
16
17
 
17
18
  describe ".artist" do
@@ -0,0 +1,78 @@
1
+ require "spec_helper"
2
+
3
+ describe Walkman::Config do
4
+ let!(:config) { Walkman::Config.new }
5
+
6
+ it "ensures only one Config object exists" do
7
+ config = Walkman.config
8
+
9
+ expect(config).to eq(Walkman.config)
10
+ end
11
+
12
+ describe "global configs" do
13
+ it "has a log level" do
14
+ expect(config.log_level).to eq("debug")
15
+
16
+ config.log_level = "info"
17
+
18
+ expect(config.log_level).to eq("info")
19
+ end
20
+ end
21
+
22
+ describe "server configs" do
23
+ it "has a server host" do
24
+ expect(config.server_host).to eq("localhost")
25
+ end
26
+
27
+ it "has a server port" do
28
+ expect(config.server_port).to eq(27001)
29
+ end
30
+
31
+ it "has a DRb URI" do
32
+ expect(config.drb_uri).to eq("druby://localhost:27001")
33
+ end
34
+ end
35
+
36
+ describe "echo nest configs" do
37
+ it "has a echo nest api key" do
38
+ expect(config.echonest_api_key).to be_nil
39
+ end
40
+
41
+ it "has a echo nest consumer key" do
42
+ expect(config.echonest_consumer_key).to be_nil
43
+ end
44
+
45
+ it "has a echo nest shared secret" do
46
+ expect(config.echonest_shared_secret).to be_nil
47
+ end
48
+
49
+ it "has a echo nest catalog id" do
50
+ expect(config.echonest_catalog_id).to be_nil
51
+ end
52
+ end
53
+
54
+ describe "rdio configs" do
55
+ it "has a rdio player url" do
56
+ expect(config.rdio_player_url).to eq("http://localhost:4567/rdio")
57
+ end
58
+
59
+ it "has a rdio playback token" do
60
+ expect(config.rdio_playback_token).to be_nil
61
+ end
62
+
63
+ it "has a rdio browser path" do
64
+ expect(config.rdio_browser_path).to eq('/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --no-process-singleton-dialog')
65
+ end
66
+ end
67
+
68
+ it "can load config values from a given YAML file" do
69
+ config_file = File.join(File.dirname(__FILE__), "..", "fixtures", "walkman.yml")
70
+ config.load_file(config_file)
71
+
72
+ expect(config.echonest_api_key).to eq("ABC")
73
+ expect(config.echonest_consumer_key).to eq("DEF")
74
+ expect(config.echonest_shared_secret).to eq("GHI")
75
+ expect(config.echonest_catalog_id).to eq("JKL")
76
+ expect(config.rdio_playback_token).to eq("MNO")
77
+ end
78
+ end
@@ -3,9 +3,22 @@ require "spec_helper"
3
3
  describe Walkman::Player do
4
4
  let!(:player) { Walkman.player }
5
5
 
6
- after :each do
7
- player.shutdown
6
+ before do
7
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
8
+ Command.stub(:run)
9
+
10
+ Walkman::Player::SERVICES.each do |service|
11
+ service.any_instance.stub(:startup)
12
+ service.any_instance.stub(:shutdown)
13
+ end
14
+
8
15
  player.playlist = nil
16
+ player.current_song = nil
17
+ player.startup
18
+ end
19
+
20
+ after do
21
+ player.shutdown
9
22
  end
10
23
 
11
24
  it "responds to #playlist" do
@@ -21,12 +34,45 @@ describe Walkman::Player do
21
34
  describe "#startup" do
22
35
  it "starts up all music services" do
23
36
  Walkman::Player::SERVICES.each do |service|
24
- service.any_instance.stub(:startup)
37
+ service.any_instance.unstub(:startup)
25
38
  expect_any_instance_of(service).to receive(:startup)
26
39
  end
27
40
 
28
41
  player.startup
29
42
  end
43
+
44
+ describe "play loop" do
45
+ it "calls #next if there is no current song" do
46
+ player.current_song = nil
47
+
48
+ expect(player).to receive(:next).at_least(1)
49
+
50
+ player.play
51
+ sleep 0.1
52
+ end
53
+
54
+ it "calls #stop if the last loop song is different than the current loop song" do
55
+ player.current_song = create(:song)
56
+ player.playlist = create(:playlist)
57
+ player.playlist.add(create(:song))
58
+
59
+ expect(player).to receive(:stop)
60
+
61
+ player.play
62
+ sleep 0.2
63
+ player.current_song = create(:song)
64
+ sleep 0.1
65
+ end
66
+
67
+ it "calls #play_song if the last loop song is nil" do
68
+ player.current_song = create(:song)
69
+
70
+ expect(player).to receive(:play_song)
71
+
72
+ player.play
73
+ sleep 0.1
74
+ end
75
+ end
30
76
  end
31
77
 
32
78
  describe "#shutdown" do
@@ -42,8 +88,6 @@ describe Walkman::Player do
42
88
 
43
89
  describe "#play" do
44
90
  it "plays a song from a specific music service" do
45
- player.startup
46
-
47
91
  Walkman::Player::SERVICES.each do |service|
48
92
  service.any_instance.stub(:play)
49
93
  player.current_song = create(:song, source_type: service.name)
@@ -51,19 +95,21 @@ describe Walkman::Player do
51
95
  end
52
96
 
53
97
  player.play
54
-
55
98
  sleep 0.2 # have to give the play loop a chance to pick up the song
56
99
  end
57
100
  end
58
101
 
59
102
  describe "#stop" do
60
103
  it "stops all music services" do
104
+ player.instance_variable_set("@play_loop", nil)
105
+
61
106
  Walkman::Player::SERVICES.each do |service|
62
107
  service.any_instance.stub(:stop)
63
108
  expect_any_instance_of(service).to receive(:stop)
64
109
  end
65
110
 
66
111
  player.stop
112
+ sleep 0.2 # have to give the play loop a chance to pick up the song
67
113
  end
68
114
  end
69
115
 
@@ -96,7 +142,7 @@ describe Walkman::Player do
96
142
  player.next
97
143
 
98
144
  expect(player.current_song).to be_nil
99
- expect(player.playing).to be_false
145
+ expect(player.playing).to eq(false)
100
146
  end
101
147
  end
102
148
  end
@@ -4,6 +4,11 @@ describe Walkman::Playlist do
4
4
  let(:playlist) { create(:playlist) }
5
5
  let(:song) { create(:song) }
6
6
 
7
+ before do
8
+ Walkman.echowrap.stub(:playlist_dynamic_feedback)
9
+ playlist.session_id = "ABC123"
10
+ end
11
+
7
12
  it "responds to #session_id" do
8
13
  expect(playlist).to respond_to(:session_id)
9
14
  end
@@ -39,13 +44,13 @@ describe Walkman::Playlist do
39
44
  it "returns true if the given song is currently queued" do
40
45
  playlist.add(song)
41
46
 
42
- expect(playlist.include?(song)).to be_true
43
- expect(playlist.queued?(song)).to be_true
47
+ expect(playlist.include?(song)).to eq(true)
48
+ expect(playlist.queued?(song)).to eq(true)
44
49
  end
45
50
 
46
51
  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
52
+ expect(playlist.include?(song)).to eq(false)
53
+ expect(playlist.queued?(song)).to eq(false)
49
54
  end
50
55
  end
51
56
 
@@ -117,12 +122,12 @@ describe Walkman::Playlist do
117
122
  end
118
123
  end
119
124
 
120
- describe "#shuffle" do
125
+ describe "#shuffle!" do
121
126
  it "changes the order of songs in the queue" do
122
127
  100.times { playlist.add(create(:song)) }
123
128
 
124
129
  expect {
125
- playlist.shuffle
130
+ playlist.shuffle!
126
131
  }.to change {
127
132
  playlist.queue.first
128
133
  }
@@ -147,4 +152,30 @@ describe Walkman::Playlist do
147
152
  expect(playlist.size).to eq(3)
148
153
  end
149
154
  end
155
+
156
+ describe "#feedback" do
157
+ it "updates favorites" do
158
+ args = { session_id: "ABC123", favorite_song: [song.echonest_song_id], favorite_artist: [song.echonest_artist_id] }
159
+
160
+ expect(Walkman.echowrap).to receive(:playlist_dynamic_feedback).with(args)
161
+
162
+ playlist.feedback(:favorite, song)
163
+ end
164
+
165
+ it "updates unplay counts" do
166
+ args = { session_id: "ABC123", unplay_song: [song.echonest_song_id] }
167
+
168
+ expect(Walkman.echowrap).to receive(:playlist_dynamic_feedback).with(args)
169
+
170
+ playlist.feedback(:unplay, song)
171
+ end
172
+
173
+ it "updates skip counts" do
174
+ args = { session_id: "ABC123", skip_song: [song.echonest_song_id] }
175
+
176
+ expect(Walkman.echowrap).to receive(:playlist_dynamic_feedback).with(args)
177
+
178
+ playlist.feedback(:skip, song)
179
+ end
180
+ end
150
181
  end
@@ -0,0 +1,30 @@
1
+ require "spec_helper"
2
+
3
+ describe Walkman do
4
+ before :each do
5
+ Walkman.class_variable_set("@@logger", nil) # reset logger
6
+ end
7
+
8
+ describe ".logger" do
9
+ it "sets the log level according to config.log_level" do
10
+ expect(Walkman.logger.level).to eq(Walkman.log_level(Walkman.config.log_level))
11
+ end
12
+
13
+ it "allows symbols when setting log level" do
14
+ [:debug, :info, :warn, :error, :fatal].each do |level|
15
+ Walkman.class_variable_set("@@logger", nil) # reset logger
16
+ Walkman.config.log_level = level
17
+
18
+ expect(Walkman.logger.level).to eq(Walkman.log_level(level))
19
+ end
20
+ end
21
+
22
+ it "raises an error if an incorrect log level is set" do
23
+ Walkman.config.log_level = :foo
24
+
25
+ expect {
26
+ Walkman.logger.level
27
+ }.to raise_error(RuntimeError)
28
+ end
29
+ end
30
+ end
data/walkman.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "walkman"
5
- spec.version = "0.1.1"
5
+ spec.version = "0.1.2"
6
6
 
7
7
  spec.author = "Tres Trantham"
8
8
  spec.email = "tres@trestrantham.com"
@@ -14,7 +14,7 @@ Gem::Specification.new do |spec|
14
14
  spec.files = `git ls-files`.split($/)
15
15
  spec.test_files = spec.files.grep(/^spec/)
16
16
  spec.require_paths = ["lib"]
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.executables = "walkman"
18
18
 
19
19
  spec.add_development_dependency "bundler", "~> 1.3"
20
20
  spec.add_development_dependency "rake", "~> 10.1"
metadata CHANGED
@@ -1,149 +1,150 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: walkman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tres Trantham
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-22 00:00:00.000000000 Z
11
+ date: 2013-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.3'
20
20
  type: :development
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: '1.3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.1'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activemodel
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 4.0.2
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 4.0.2
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: colorize
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.6.0
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.6.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: command
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
75
  version: '1.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '1.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: echowrap
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ~>
87
+ - - "~>"
88
88
  - !ruby/object:Gem::Version
89
89
  version: 0.1.0
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - ~>
94
+ - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.1.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: sinatra
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - ~>
101
+ - - "~>"
102
102
  - !ruby/object:Gem::Version
103
103
  version: 1.4.4
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ~>
108
+ - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 1.4.4
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: thor
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - ~>
115
+ - - "~>"
116
116
  - !ruby/object:Gem::Version
117
117
  version: 0.18.1
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - ~>
122
+ - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: 0.18.1
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: titleize
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ~>
129
+ - - "~>"
130
130
  - !ruby/object:Gem::Version
131
131
  version: 1.3.0
132
132
  type: :runtime
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - ~>
136
+ - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: 1.3.0
139
139
  description: Control your music
140
140
  email: tres@trestrantham.com
141
- executables: []
141
+ executables:
142
+ - walkman
142
143
  extensions: []
143
144
  extra_rdoc_files: []
144
145
  files:
145
- - .gitignore
146
- - .travis.yml
146
+ - ".gitignore"
147
+ - ".travis.yml"
147
148
  - Gemfile
148
149
  - LICENSE.txt
149
150
  - README.md
@@ -156,6 +157,7 @@ files:
156
157
  - lib/walkman/commands/playlist.rb
157
158
  - lib/walkman/commands/queueing.rb
158
159
  - lib/walkman/config.rb
160
+ - lib/walkman/logger.rb
159
161
  - lib/walkman/player.rb
160
162
  - lib/walkman/playlist.rb
161
163
  - lib/walkman/services/base.rb
@@ -165,20 +167,26 @@ files:
165
167
  - spec/factories/echowrap.rb
166
168
  - spec/factories/playlist.rb
167
169
  - spec/factories/song.rb
170
+ - spec/fixtures/walkman.yml
168
171
  - spec/sinatra_helper.rb
169
172
  - spec/spec_helper.rb
170
173
  - spec/support/factory_girl.rb
174
+ - spec/support/rspec.rb
171
175
  - spec/walkman/commands/controls_spec.rb
172
176
  - spec/walkman/commands/information_spec.rb
173
177
  - spec/walkman/commands/player_spec.rb
178
+ - spec/walkman/commands/playlist_spec.rb
174
179
  - spec/walkman/commands/queueing_spec.rb
180
+ - spec/walkman/config_spec.rb
175
181
  - spec/walkman/player_spec.rb
176
182
  - spec/walkman/playlist_spec.rb
177
183
  - spec/walkman/services/base_spec.rb
178
184
  - spec/walkman/services/rdio/rdio_player_spec.rb
179
185
  - spec/walkman/services/rdio_spec.rb
180
186
  - spec/walkman/song_spec.rb
187
+ - spec/walkman_spec.rb
181
188
  - walkman.gemspec
189
+ - bin/walkman
182
190
  homepage: https://github.com/trestrantham/walkman
183
191
  licenses:
184
192
  - MIT
@@ -189,12 +197,12 @@ require_paths:
189
197
  - lib
190
198
  required_ruby_version: !ruby/object:Gem::Requirement
191
199
  requirements:
192
- - - '>='
200
+ - - ">="
193
201
  - !ruby/object:Gem::Version
194
202
  version: '0'
195
203
  required_rubygems_version: !ruby/object:Gem::Requirement
196
204
  requirements:
197
- - - '>='
205
+ - - ">="
198
206
  - !ruby/object:Gem::Version
199
207
  version: '0'
200
208
  requirements: []
@@ -207,16 +215,21 @@ test_files:
207
215
  - spec/factories/echowrap.rb
208
216
  - spec/factories/playlist.rb
209
217
  - spec/factories/song.rb
218
+ - spec/fixtures/walkman.yml
210
219
  - spec/sinatra_helper.rb
211
220
  - spec/spec_helper.rb
212
221
  - spec/support/factory_girl.rb
222
+ - spec/support/rspec.rb
213
223
  - spec/walkman/commands/controls_spec.rb
214
224
  - spec/walkman/commands/information_spec.rb
215
225
  - spec/walkman/commands/player_spec.rb
226
+ - spec/walkman/commands/playlist_spec.rb
216
227
  - spec/walkman/commands/queueing_spec.rb
228
+ - spec/walkman/config_spec.rb
217
229
  - spec/walkman/player_spec.rb
218
230
  - spec/walkman/playlist_spec.rb
219
231
  - spec/walkman/services/base_spec.rb
220
232
  - spec/walkman/services/rdio/rdio_player_spec.rb
221
233
  - spec/walkman/services/rdio_spec.rb
222
234
  - spec/walkman/song_spec.rb
235
+ - spec/walkman_spec.rb