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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8e3d7ee1e1eeb85342fc9df700432e1a1879cf58
|
4
|
+
data.tar.gz: 7538521e2f9691d497aa9f780279fe6034d995d0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fb245267ddb8f2c75c0cf3711ee9d4006df6c2deefed5985cabb458d0b0bd38a48d6cce3c04fdca97ab3fa0fa397838cc2d9c14f6c2af7571a3bb657471cb20f
|
7
|
+
data.tar.gz: 549890eeb0a29f384329909e17d59d71ac0b69060489aad7d19f55a97a0adb0461e74d0b16f8f67a21cf2c7945e3b5e039ee25e2012314d33ad689182b4f7ef9
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Tres Trantham
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Walkman
|
2
|
+
|
3
|
+
[](https://travis-ci.org/trestrantham/walkman)
|
4
|
+
[](https://codeclimate.com/github/trestrantham/walkman)
|
5
|
+
[](https://coveralls.io/r/trestrantham/walkman)
|
6
|
+
[](https://gemnasium.com/trestrantham/walkman)
|
7
|
+
|
8
|
+
Walkman puts you in control if your music.
|
9
|
+
|
10
|
+
## Install
|
11
|
+
|
12
|
+
```
|
13
|
+
gem install walkman
|
14
|
+
```
|
15
|
+
|
16
|
+
## Dependencies
|
17
|
+
|
18
|
+
Walkman relies on a few external services to do its magic. Currently, the
|
19
|
+
canonical source for music data comes from [Echo Nest](http://echonest.com) who
|
20
|
+
provides artist/album/song information as well as playlist generation and
|
21
|
+
seeding. Actual music streams are currently provided via [Rdio](http://rdio.com)
|
22
|
+
with support for [Spotify](http://spotify.com) and local file playback via
|
23
|
+
[MPD](http://musicpd.org) in the works.
|
24
|
+
|
25
|
+
### Echo Nest
|
26
|
+
|
27
|
+
1. [Sign up](https://developer.echonest.com/account/register) for an Echo Nest developer account
|
28
|
+
2. Grab the `api_key`, `consumer_key`, and `shared_secret`
|
29
|
+
3. Create a catalog (taste profile) to use as your base library and grab its `id` to use as `catalog_id`:
|
30
|
+
|
31
|
+
```
|
32
|
+
curl -F "api_key=<api_key>" -F "format=json" -F "type=general" -F "name=base_profile"
|
33
|
+
```
|
34
|
+
|
35
|
+
### Rdio
|
36
|
+
|
37
|
+
1. [Sign up](http://developer.rdio.com/member/register) for a Rdio developer account
|
38
|
+
2. [Generate](http://rdioconsole.appspot.com/#method=getPlaybackToken) a `playback_token` after logging in at [rdio.com](http://rdio.com).
|
39
|
+
|
40
|
+
### Config
|
41
|
+
|
42
|
+
Create a Walkman config file at `~/.walkman`:
|
43
|
+
|
44
|
+
```
|
45
|
+
echonest:
|
46
|
+
api_key: ABCDEFGHIJKLMNOP
|
47
|
+
consumer_key: abc123efg456hij789klm098nop765qr
|
48
|
+
shared_secret: 4jh&kjhfg.@3kjfl987FJ3
|
49
|
+
catalog_id: CACABCD1234567890Z
|
50
|
+
rdio:
|
51
|
+
playback_token: GAlNi78J_____zlyYWs5ZG02N2pkaHlhcWsyOWJtYjkyN2xvY2FsaG9zdEbwl7EHvbylWSWFWYMZwfc=
|
52
|
+
```
|
data/Rakefile
ADDED
data/lib/walkman.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "echowrap"
|
2
|
+
|
3
|
+
require "walkman/config"
|
4
|
+
|
5
|
+
require "walkman/services/base"
|
6
|
+
require "walkman/services/rdio"
|
7
|
+
require "walkman/services/rdio/rdio_player"
|
8
|
+
|
9
|
+
require "walkman/player"
|
10
|
+
require "walkman/playlist"
|
11
|
+
require "walkman/song"
|
12
|
+
|
13
|
+
require "walkman/commands/controls"
|
14
|
+
require "walkman/commands/information"
|
15
|
+
require "walkman/commands/player"
|
16
|
+
require "walkman/commands/playlist"
|
17
|
+
require "walkman/commands/queueing"
|
18
|
+
|
19
|
+
require "walkman/cli"
|
20
|
+
|
21
|
+
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
|
+
def self.echowrap
|
51
|
+
@echowrap ||= Echowrap.configure do |config|
|
52
|
+
config.api_key = Walkman.config.echonest_api_key
|
53
|
+
config.consumer_key = Walkman.config.echonest_consumer_key
|
54
|
+
config.shared_secret = Walkman.config.echonest_shared_secret
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/walkman/cli.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "drb"
|
3
|
+
require "colorize"
|
4
|
+
|
5
|
+
module Walkman
|
6
|
+
class CLI < Thor
|
7
|
+
|
8
|
+
# server tasks
|
9
|
+
|
10
|
+
desc "start", "starts the walkman server"
|
11
|
+
option :daemon, type: :boolean, aliases: "-d"
|
12
|
+
def start
|
13
|
+
if options[:daemon]
|
14
|
+
Process.daemon
|
15
|
+
else
|
16
|
+
puts "Starting walkman server"
|
17
|
+
puts "Run `walkman start -d` for daemon"
|
18
|
+
puts "Ctrl-C to shutdown"
|
19
|
+
|
20
|
+
trap("INT") do
|
21
|
+
# calling this in a thread to get proper logging
|
22
|
+
thread = Thread.new do
|
23
|
+
shutdown
|
24
|
+
end
|
25
|
+
|
26
|
+
thread.join
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
Walkman.logger.info("starting server")
|
31
|
+
Walkman::Commands::Player.start
|
32
|
+
|
33
|
+
DRb.start_service(Walkman.config.drb_uri, self)
|
34
|
+
DRb.thread.join
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "shutdown", "stops the walkman server"
|
38
|
+
def shutdown
|
39
|
+
response = server.run_command(:player_stop)
|
40
|
+
puts response unless response.empty?
|
41
|
+
|
42
|
+
server.stop_server
|
43
|
+
end
|
44
|
+
|
45
|
+
# controls tasks
|
46
|
+
|
47
|
+
desc "play", "plays the current playlist"
|
48
|
+
def play
|
49
|
+
response = server.run_command(:play)
|
50
|
+
puts response unless response.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "stop", "stops playing music"
|
54
|
+
def stop
|
55
|
+
response = server.run_command(:stop)
|
56
|
+
puts response unless response.empty?
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "next", "plays the next song in the current playlist"
|
60
|
+
def next(count = 1)
|
61
|
+
response = server.run_command(:next, { count: count.to_i })
|
62
|
+
puts response unless response.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "skip COUNT", "skips the given amount of songs"
|
66
|
+
def skip(count = 1)
|
67
|
+
response = server.run_command(:skip, { count: count.to_i })
|
68
|
+
puts response unless response.empty?
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "now_playing", "shows the song that's currently playing"
|
72
|
+
def now_playing
|
73
|
+
response = server.run_command(:now_playing)
|
74
|
+
puts response unless response.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
desc "up_next", "shows the next songs on the current playlist"
|
78
|
+
def up_next
|
79
|
+
response = server.run_command(:up_next)
|
80
|
+
puts response unless response.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "play_artist ARTIST", "plays songs from the given artist"
|
84
|
+
def play_artist(*artist)
|
85
|
+
artist = artist.join(" ")
|
86
|
+
response = server.run_command(:artist, { artist: artist })
|
87
|
+
puts response unless response.empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
desc "play_artist_radio ARTIST", "plays music like the given artist"
|
91
|
+
def play_artist_radio(*artist)
|
92
|
+
artist = artist.join(" ")
|
93
|
+
response = server.run_command(:artist_radio, { artist: artist })
|
94
|
+
puts response unless response.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
desc "like", "plays more music like the current song"
|
98
|
+
def like
|
99
|
+
response = server.run_command(:like)
|
100
|
+
puts response unless response.empty?
|
101
|
+
end
|
102
|
+
|
103
|
+
no_tasks do
|
104
|
+
def stop_server
|
105
|
+
DRb.stop_service
|
106
|
+
end
|
107
|
+
|
108
|
+
def server
|
109
|
+
@server ||= DRbObject.new_with_uri(Walkman.config.drb_uri)
|
110
|
+
end
|
111
|
+
|
112
|
+
def run_command(command, options = {})
|
113
|
+
case command
|
114
|
+
when :player_stop then Walkman::Commands::Player.stop
|
115
|
+
when :play then Walkman::Commands::Controls.play
|
116
|
+
when :stop then Walkman::Commands::Controls.stop
|
117
|
+
when :next then Walkman::Commands::Controls.next(options[:count])
|
118
|
+
when :skip then Walkman::Commands::Controls.skip(options[:count])
|
119
|
+
when :up_next then Walkman::Commands::Information.up_next
|
120
|
+
when :now_playing then Walkman::Commands::Information.now_playing
|
121
|
+
when :artist then Walkman::Commands::Queueing.artist(options[:artist])
|
122
|
+
when :artist_radio then Walkman::Commands::Queueing.artist_radio(options[:artist])
|
123
|
+
when :like then Walkman::Commands::Playlist.like
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Walkman
|
2
|
+
module Commands
|
3
|
+
module Controls
|
4
|
+
def self.play
|
5
|
+
Walkman.player.play
|
6
|
+
song = Walkman.player.current_song
|
7
|
+
|
8
|
+
output = ["♫".blue, "Playing"]
|
9
|
+
output << [song.title.bold, "by", song.artist.bold] if song
|
10
|
+
output.flatten.join(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.stop
|
14
|
+
Walkman.player.stop
|
15
|
+
""
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.next(count = 1)
|
19
|
+
if current_song = Walkman.player.current_song
|
20
|
+
Walkman.player.playlist.skip(current_song)
|
21
|
+
end
|
22
|
+
|
23
|
+
Walkman.player.next(count)
|
24
|
+
song = Walkman.player.current_song
|
25
|
+
|
26
|
+
output = ["♫".blue, "Skipping"]
|
27
|
+
output << ["to", song.title.bold, "by", song.artist.bold] if song
|
28
|
+
output.flatten.join(" ")
|
29
|
+
end
|
30
|
+
define_singleton_method(:skip) { |count| self.next(count) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Walkman
|
2
|
+
module Commands
|
3
|
+
module Information
|
4
|
+
def self.now_playing
|
5
|
+
if song = Walkman.player.current_song
|
6
|
+
output = ["♫".blue, "Now playing"]
|
7
|
+
output << [song.title.bold, "by", song.artist.bold]
|
8
|
+
output.flatten.join(" ")
|
9
|
+
else
|
10
|
+
"No music is playing"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.up_next(count = 5)
|
15
|
+
songs = Walkman.player.playlist.queue.take(count)
|
16
|
+
songs_string = ""
|
17
|
+
|
18
|
+
songs.each do |song|
|
19
|
+
songs_string += "#{song.artist} - #{song.title}\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
songs_string
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Walkman
|
2
|
+
module Commands
|
3
|
+
module Playlist
|
4
|
+
def self.like
|
5
|
+
current_song = Walkman.player.current_song
|
6
|
+
playlist = Walkman.player.playlist
|
7
|
+
|
8
|
+
if current_song && playlist
|
9
|
+
playlist.favorite(current_song)
|
10
|
+
"Awesome! I'll play more songs like this."
|
11
|
+
else
|
12
|
+
"No music is playing. Are you hearing things?"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Walkman
|
2
|
+
module Commands
|
3
|
+
module Queueing
|
4
|
+
def self.artist(artist)
|
5
|
+
playlist = Walkman::Playlist.new(type: "artist", artist: artist, auto_queue: true)
|
6
|
+
Walkman.player.playlist = playlist
|
7
|
+
|
8
|
+
if playlist.size > 0
|
9
|
+
Walkman.player.next
|
10
|
+
output = ["♫".blue, "Playing songs by", artist.titleize.bold]
|
11
|
+
output.flatten.join(" ")
|
12
|
+
else
|
13
|
+
"That artist couldn't be queued"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.artist_radio(artist)
|
18
|
+
playlist = Walkman::Playlist.new(type: "artist-radio", artist: artist, auto_queue: true)
|
19
|
+
Walkman.player.playlist = playlist
|
20
|
+
|
21
|
+
if playlist.size > 0
|
22
|
+
Walkman.player.next
|
23
|
+
output = ["♫".blue, "Playing music like", artist.titleize.bold]
|
24
|
+
output.flatten.join(" ")
|
25
|
+
else
|
26
|
+
"Music like that artist couldn't be queued"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|