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 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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ branches:
2
+ only:
3
+ - master
4
+ language: ruby
5
+ rvm:
6
+ - 2.0.0
7
+ script: rspec
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "coveralls", "~> 0.7", require: false
7
+ gem "factory_girl", "4.3.0"
8
+ gem "rack-test", "~> 0.6.2"
9
+ gem "rspec", "~> 2.14"
10
+ end
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
+ [![Build Status](https://travis-ci.org/trestrantham/walkman.png?branch=master)](https://travis-ci.org/trestrantham/walkman)
4
+ [![Code Climate](https://codeclimate.com/github/trestrantham/walkman.png)](https://codeclimate.com/github/trestrantham/walkman)
5
+ [![Coverage Status](https://coveralls.io/repos/trestrantham/walkman/badge.png)](https://coveralls.io/r/trestrantham/walkman)
6
+ [![Dependency Status](https://gemnasium.com/trestrantham/walkman.png)](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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
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
@@ -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,15 @@
1
+ module Walkman
2
+ module Commands
3
+ module Player
4
+ def self.start
5
+ Walkman.player.startup
6
+ "All systems go"
7
+ end
8
+
9
+ def self.stop
10
+ Walkman.player.shutdown
11
+ "Powering down"
12
+ end
13
+ end
14
+ end
15
+ 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