class MusicBox::Player
Constants
- Keymap
- ObservedProperties
- SeekSeconds
Attributes
albums[RW]
audio_device[RW]
equalizers[RW]
mpv_log_level[RW]
Public Class Methods
new(**params)
click to toggle source
# File lib/musicbox/player.rb, line 34 def initialize(**params) { mpv_log_level: 'error', }.merge(params).each { |k, v| send("#{k}=", v) } @playlist_file = Path.new('/tmp/mpv_playlist') end
Public Instance Methods
next_equalizer()
click to toggle source
# File lib/musicbox/player.rb, line 243 def next_equalizer if @equalizers @current_equalizer &&= @equalizers[@equalizers.index(@current_equalizer) + 1] @current_equalizer ||= @equalizers.first set_current_equalizer end end
play()
click to toggle source
# File lib/musicbox/player.rb, line 41 def play raise Error, "No albums to play" if @albums.nil? || @albums.empty? read_albums @dispatcher = IO::Dispatcher.new setup_interface setup_mpv puts "[ready]" play_random_album @dispatcher.run end
play_album_for_current_track()
click to toggle source
# File lib/musicbox/player.rb, line 173 def play_album_for_current_track if @properties.playlist_position entry = @properties.playlist[@properties.playlist_position] track_path = Path.new(entry.filename) album = @album_for_track_path[track_path] \ or raise Error, "Can't determine album for track file: #{track_path}" play_tracks(album.tracks) else puts "no current track" end end
play_next_track()
click to toggle source
# File lib/musicbox/player.rb, line 149 def play_next_track if @properties.playlist_position && @properties.playlist_position < @properties.playlist.count - 1 @mpv.command('playlist-next') else puts 'no next track' end end
play_previous_track()
click to toggle source
# File lib/musicbox/player.rb, line 157 def play_previous_track if @properties.playlist_position && @properties.playlist_position > 0 @mpv.command('playlist-prev') else puts 'no previous track' end end
play_random_album()
click to toggle source
# File lib/musicbox/player.rb, line 165 def play_random_album play_tracks(random_album.tracks) end
play_random_tracks()
click to toggle source
# File lib/musicbox/player.rb, line 169 def play_random_tracks play_tracks(random_tracks(length: 10)) end
play_tracks(tracks)
click to toggle source
# File lib/musicbox/player.rb, line 232 def play_tracks(tracks) @playlist_file.dirname.mkpath @playlist_file.write(tracks.map(&:path).join("\n")) @mpv.command('loadlist', @playlist_file.to_s) end
playlist_changed(value)
click to toggle source
# File lib/musicbox/player.rb, line 125 def playlist_changed(value) @current_track = @playlist = nil if @properties.playlist @playlist = @properties.playlist.map do |entry| track_path = Path.new(entry.filename) album = @album_for_track_path[track_path] \ or raise Error, "Can't determine album for track file: #{track_path}" track = album.tracks.find { |t| t.path == track_path } \ or raise Error, "Can't determine track for track file: #{track_path}" @current_track = track if entry.current track end end show_playlist end
property_changed(name, value)
click to toggle source
callbacks from MPV
# File lib/musicbox/player.rb, line 265 def property_changed(name, value) # ;;pp(name => value) unless name == 'time-pos' key = ObservedProperties[name] or raise @properties[key] = value send("#{key}_changed", value) rescue NoMethodError end
quit()
click to toggle source
commands called by interface
# File lib/musicbox/player.rb, line 145 def quit Kernel.exit(0) end
random_album()
click to toggle source
# File lib/musicbox/player.rb, line 113 def random_album @albums.shuffle.first end
random_tracks(length:)
click to toggle source
# File lib/musicbox/player.rb, line 117 def random_tracks(length:) tracks = Set.new while tracks.length < length tracks << random_album.tracks.shuffle.first end tracks.to_a end
read_albums()
click to toggle source
# File lib/musicbox/player.rb, line 104 def read_albums @album_for_track_path = {} @albums.each do |album| album.tracks.each do |track| @album_for_track_path[track.path] = album end end end
set_current_equalizer()
click to toggle source
# File lib/musicbox/player.rb, line 251 def set_current_equalizer if @current_equalizer puts "[equalizer: %s <%s>]" % [ @current_equalizer.name, @equalizer_enabled ? 'enabled' : 'disabled', ] @mpv.command('af', 'set', @current_equalizer.to_s(enabled: @equalizer_enabled)) end end
setup_interface()
click to toggle source
# File lib/musicbox/player.rb, line 89 def setup_interface @stty_old_params = `stty -g`.chomp at_exit { system('stty', @stty_old_params) } system('stty', 'cbreak', '-echo') @dispatcher.add_io_handler(input: STDIN) do |io| key = io.sysread(1) if (command = Keymap[key]) puts "[#{command_description(command)}]" send(command) else puts "unknown key: %p" % key end end end
setup_mpv()
click to toggle source
# File lib/musicbox/player.rb, line 52 def setup_mpv @mpv = MPVClient.new( 'mpv-log-level' => @mpv_log_level, 'audio-device' => @audio_device, 'audio-display' => 'no', 'vo' => 'null', 'volume' => 100) @mpv.register_event('log-message') do |event| ;;pp(log: event) end @mpv.command('request_log_messages', @mpv_log_level) if @mpv_log_level @properties = HashStruct.new ObservedProperties.each do |name, key| @mpv.observe_property(name) { |n, v| property_changed(n, v) } end if @equalizers @equalizer_enabled = true next_equalizer end @dispatcher.add_io_handler(input: @mpv.socket) do |io| @mpv.process_response end @dispatcher.add_io_handler(exception: @mpv.socket) do |io| shutdown_mpv end at_exit { shutdown_mpv } end
show_keymap()
click to toggle source
# File lib/musicbox/player.rb, line 226 def show_keymap Keymap.each do |key, command| puts "%-8s %s" % [key_description(key), command_description(command)] end end
show_playlist()
click to toggle source
# File lib/musicbox/player.rb, line 207 def show_playlist if @playlist system('clear') if @current_track @current_track.album.show_cover(width: 'auto', height: 20, preserve_aspect_ratio: false) puts end @playlist.each_with_index do |track, i| puts '%1s %2d. %-40.40s | %-40.40s | %-40.40s' % [ track == @current_track ? '>' : '', i + 1, track.title, track.album.title, track.album.artist, ] end end end
shutdown_mpv()
click to toggle source
# File lib/musicbox/player.rb, line 80 def shutdown_mpv if @mpv @mpv.command('quit') @dispatcher.remove_io_handler(input: @mpv.socket, exception: @mpv.socket) @mpv.stop @mpv = nil end end
skip_backward()
click to toggle source
# File lib/musicbox/player.rb, line 189 def skip_backward if @properties.time_position && @properties.time_position > 0 @mpv.command('seek', -SeekSeconds) end end
skip_forward()
click to toggle source
# File lib/musicbox/player.rb, line 195 def skip_forward if @properties.time_position @mpv.command('seek', SeekSeconds) end end
skip_to_beginning()
click to toggle source
# File lib/musicbox/player.rb, line 201 def skip_to_beginning if @properties.time_position && @properties.time_position > 0 @mpv.command('seek', 0, 'absolute-percent') end end
toggle_equalizer()
click to toggle source
# File lib/musicbox/player.rb, line 238 def toggle_equalizer @equalizer_enabled = !@equalizer_enabled set_current_equalizer end
toggle_pause()
click to toggle source
# File lib/musicbox/player.rb, line 185 def toggle_pause @mpv.set_property('pause', !@properties.pause_state) end
Private Instance Methods
command_description(command)
click to toggle source
# File lib/musicbox/player.rb, line 283 def command_description(command) command.to_s.gsub('_', ' ') end
key_description(key)
click to toggle source
# File lib/musicbox/player.rb, line 274 def key_description(key) case key when ' ' 'space' else key end end