partygoer-player 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/lib/partygoer-player/support.rb +47 -0
- data/lib/partygoer-player.rb +174 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8de5eedf33fdf8d92d9a529e7e388c2e73fa2f1a
|
4
|
+
data.tar.gz: 2203335b57f79b2a9ae9209e0cb71377e6fa8047
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ae09b7f31645833b5b3193ad0fdbf34730690de1591169ffd0935faee6152d55e926cee90fc224fd5ba80805554e3a04d7f177137471e1f45faf957fdfedee6f
|
7
|
+
data.tar.gz: 587e28e8f27bd002c21b185fb0129b2d22ff200c0732a3a858612e6f676794939d2152a5b41fc682777b589678d2679b6cd6ad2cee7149fd8b2826c96320483e
|
data/.gitignore
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
require 'spotify'
|
4
|
+
|
5
|
+
module Support
|
6
|
+
module_function
|
7
|
+
|
8
|
+
@@logger = Logger.new('support.log', 2, 1_000_000)
|
9
|
+
@@logger.formatter = proc do |severity, datetime, _progname, msg|
|
10
|
+
"\n\n#{datetime} #{severity}:\n\t#{msg}"
|
11
|
+
end
|
12
|
+
@@logger.level = Logger::DEBUG
|
13
|
+
|
14
|
+
DEFAULT_CONFIG = {
|
15
|
+
api_version: Spotify::API_VERSION.to_i,
|
16
|
+
application_key: File.binread('spotify_appkey.key'),
|
17
|
+
cache_location: '.spotify/',
|
18
|
+
settings_location: '.spotify/',
|
19
|
+
user_agent: 'Partygoer',
|
20
|
+
callbacks: Spotify::SessionCallbacks.new
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize_spotify!(username, password, config = DEFAULT_CONFIG)
|
24
|
+
error, session = Spotify.session_create(config)
|
25
|
+
raise error if error.is_a?(Spotify::APIError)
|
26
|
+
|
27
|
+
if Spotify.session_remembered_user(session)
|
28
|
+
@@logger.info { "Using remembered login for: #{Spotify.session_remembered_user(session)}." }
|
29
|
+
Spotify.try(:session_relogin, session)
|
30
|
+
else
|
31
|
+
@@logger.info "Attempting login under #{username}."
|
32
|
+
Spotify.try(:session_login, session, username, password, true, nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
@@logger.info 'Log in requested. Waiting forever until logged in.'
|
36
|
+
until (Spotify.session_connectionstate(session) == :logged_in)
|
37
|
+
Spotify.session_process_events(session)
|
38
|
+
end
|
39
|
+
|
40
|
+
at_exit do
|
41
|
+
@@logger.info { 'Logging out.' }
|
42
|
+
Spotify.session_logout(session)
|
43
|
+
Spotify.session_process_events(session) until (Spotify.session_connectionstate(session) != :logged_in )
|
44
|
+
end
|
45
|
+
session
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
require 'plaything'
|
8
|
+
require 'partygoer-client'
|
9
|
+
|
10
|
+
require_relative 'partygoer-player/support'
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
module PartyGoerPlayer
|
15
|
+
|
16
|
+
@@logger = Logger.new('partygoer-player.log', 2, 1_000_000)
|
17
|
+
@@logger.formatter = proc do |severity, datetime, _progname, msg|
|
18
|
+
"\n\n#{datetime} #{severity}:\n\t#{msg}"
|
19
|
+
end
|
20
|
+
@@logger.level = Logger::DEBUG
|
21
|
+
|
22
|
+
client = PartyGoerClient.new('http://partygoer.io')
|
23
|
+
|
24
|
+
@@playign = false
|
25
|
+
|
26
|
+
|
27
|
+
def self.play_track(session, uri)
|
28
|
+
track = Spotify.link_as_track(Spotify.link_create_from_string(uri))
|
29
|
+
Spotify.session_process_events(session) until Spotify.track_is_loaded(track)
|
30
|
+
|
31
|
+
# Pause before we load a new track. Fixes a quirk in libspotify.
|
32
|
+
Spotify.try(:session_player_play, session, false)
|
33
|
+
Spotify.try(:session_player_load, session, track)
|
34
|
+
Spotify.try(:session_player_play, session, true)
|
35
|
+
@@playing = true
|
36
|
+
@@logger.info {"Playing next track: #{uri}"}
|
37
|
+
rescue
|
38
|
+
# Log something
|
39
|
+
@@playing = false
|
40
|
+
end
|
41
|
+
|
42
|
+
class FrameReader
|
43
|
+
include Enumerable
|
44
|
+
|
45
|
+
def initialize(channels, sample_type, frames_count, frames_ptr)
|
46
|
+
@channels = channels
|
47
|
+
@sample_type = sample_type
|
48
|
+
@size = frames_count * @channels
|
49
|
+
@pointer = FFI::Pointer.new(@sample_type, frames_ptr)
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_reader :size
|
53
|
+
|
54
|
+
def each
|
55
|
+
return enum_for(__method__) unless block_given?
|
56
|
+
|
57
|
+
ffi_read = :"read_#{@sample_type}"
|
58
|
+
|
59
|
+
(0...size).each do |index|
|
60
|
+
yield @pointer[index].public_send(ffi_read)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
plaything = Plaything.new
|
66
|
+
|
67
|
+
$session_callbacks = {
|
68
|
+
log_message: proc do |_session, message|
|
69
|
+
@@logger.info { "Message from spotify: #{message}" }
|
70
|
+
end,
|
71
|
+
|
72
|
+
logged_in: proc do |_session, error|
|
73
|
+
@@logger.debug { "Logged in: #{error}" }
|
74
|
+
end,
|
75
|
+
|
76
|
+
logged_out: proc do |_session|
|
77
|
+
@@logger.debug { 'Logged out!' }
|
78
|
+
end,
|
79
|
+
|
80
|
+
streaming_error: proc do |_session, error|
|
81
|
+
@@logger.error { "Streaming error #{error.message}" }
|
82
|
+
end,
|
83
|
+
|
84
|
+
connection_error: proc do |_session, error|
|
85
|
+
@@logger.error { "Connection error: #{error}" }
|
86
|
+
end,
|
87
|
+
|
88
|
+
play_token_lost: proc do |_session|
|
89
|
+
@@logger.error { 'Play token lost. Stopping playback.' }
|
90
|
+
plaything.stop
|
91
|
+
@@playing = false
|
92
|
+
end,
|
93
|
+
|
94
|
+
streaming_error: proc do |_session, error|
|
95
|
+
@@logger.error { "Streaming error #{error}. Stopping playback" }
|
96
|
+
plaything.stop
|
97
|
+
@@playing = false
|
98
|
+
end,
|
99
|
+
|
100
|
+
start_playback: proc do |_session|
|
101
|
+
@@logger.debug { 'Starting playback' }
|
102
|
+
plaything.play
|
103
|
+
end,
|
104
|
+
|
105
|
+
stop_playback: proc do |_session|
|
106
|
+
@@logger.debug { 'Stopping playback' }
|
107
|
+
plaything.stop
|
108
|
+
end,
|
109
|
+
|
110
|
+
get_audio_buffer_stats: proc do |_session, stats|
|
111
|
+
stats[:samples] = plaything.queue_size
|
112
|
+
stats[:stutter] = plaything.drops
|
113
|
+
end,
|
114
|
+
|
115
|
+
music_delivery: proc do |_session, format, frames, num_frames|
|
116
|
+
if num_frames == 0
|
117
|
+
@@logger.error { 'Music delivery audio discontuity' }
|
118
|
+
plaything.stop
|
119
|
+
0
|
120
|
+
else
|
121
|
+
@@logger.error { "#{num_frames} frames delivered. #{format.to_h.inspect}" }
|
122
|
+
frames = FrameReader.new(
|
123
|
+
format[:channels], format[:sample_type], num_frames, frames)
|
124
|
+
consumed_frames = plaything.stream(frames, format.to_h)
|
125
|
+
consumed_frames
|
126
|
+
end
|
127
|
+
end,
|
128
|
+
|
129
|
+
end_of_track: proc do |session|
|
130
|
+
@@logger.info { 'End of track' }
|
131
|
+
plaything.stop
|
132
|
+
if client.up_next
|
133
|
+
play_track(session, client.up_next['spotify_uri'])
|
134
|
+
client.playing = client.up_next
|
135
|
+
@@playing = true
|
136
|
+
else
|
137
|
+
@@playing = false
|
138
|
+
end
|
139
|
+
end
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
Support::DEFAULT_CONFIG[:callbacks] = Spotify::SessionCallbacks.new(
|
144
|
+
$session_callbacks)
|
145
|
+
|
146
|
+
CONFIG = YAML.load_file('config.yml')
|
147
|
+
|
148
|
+
session = Support.initialize_spotify!(CONFIG['username'], CONFIG['password'])
|
149
|
+
|
150
|
+
play_track(session, client.playing['spotify_uri']) if client.playing
|
151
|
+
|
152
|
+
loop do
|
153
|
+
Spotify.session_process_events(session)
|
154
|
+
if client.skip?
|
155
|
+
@@logger.info { 'Skipping track' }
|
156
|
+
if client.up_next
|
157
|
+
play_track(session, client.up_next['spotify_uri'])
|
158
|
+
client.playing = client.up_next
|
159
|
+
else
|
160
|
+
@@playing = false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
unless @@playing
|
164
|
+
@@logger.info { 'Nothing playing, attempting to play next track' }
|
165
|
+
if client.up_next
|
166
|
+
play_track(session, client.up_next['spotify_uri'])
|
167
|
+
client.playing = client.up_next
|
168
|
+
else
|
169
|
+
@@playing = false
|
170
|
+
end
|
171
|
+
end
|
172
|
+
sleep(0.05)
|
173
|
+
end
|
174
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: partygoer-player
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Hamon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: spotify
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '12.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '12.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: plaything
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: partygoer-client
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.0.4
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.0.4
|
55
|
+
description: Uses the spotify gem and partygoer-client to play your partygoer queue
|
56
|
+
email: andrew@hamon.cc
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- ".gitignore"
|
62
|
+
- lib/partygoer-player.rb
|
63
|
+
- lib/partygoer-player/support.rb
|
64
|
+
homepage: http://github.com/andrewhamon/partygoer-player
|
65
|
+
licenses:
|
66
|
+
- MIT
|
67
|
+
metadata: {}
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.9.2
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
requirements: []
|
83
|
+
rubyforge_project:
|
84
|
+
rubygems_version: 2.4.2
|
85
|
+
signing_key:
|
86
|
+
specification_version: 4
|
87
|
+
summary: Play your partygoer queue!
|
88
|
+
test_files: []
|
89
|
+
has_rdoc:
|