walkman 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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