class MPV::Handle

typedef enum mpv_sub_api void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api);

Constants

MPVLogMessageLevels

Attributes

audio_device[RW]
delegate[RW]
equalizer[RW]
mpv_log_level[RW]
playlist_file[RW]
wakeup_pipe[R]

Public Class Methods

new( playlist_file: nil, audio_device: nil, mpv_log_level: nil, equalizer: nil, delegate: nil, **params ) click to toggle source
# File lib/mpvlib/handle.rb, line 70
def initialize(
  playlist_file: nil,
  audio_device: nil,
  mpv_log_level: nil,
  equalizer: nil,
  delegate: nil,
  **params
)
  @playlist_file = Path.new(playlist_file || '/tmp/playlist.txt')
  @audio_device = audio_device
  @mpv_log_level = mpv_log_level || 'error'
  @equalizer = equalizer
  @delegate = delegate
  @property_observers = {}
  @event_observers = {}
  @reply_id = 1
  @mpv_handle = MPV.mpv_create
  MPV::Error.raise_on_failure("initialize") {
    MPV.mpv_initialize(@mpv_handle)
  }
  define_finalizer(:mpv_terminate_destroy, @mpv_handle)
  fd = MPV.mpv_get_wakeup_pipe(@mpv_handle)
  raise StandardError, "Couldn't get wakeup pipe from MPV" if fd < 0
  @wakeup_pipe = IO.new(fd)
  register_event('log-message') { |e| handle_log_message(e) }
  request_log_messages(@mpv_log_level)
  set_option('audio-device', @audio_device) if @audio_device
  command('af', 'add', "equalizer=#{@equalizer.join(':')}") if @equalizer
  set_option('audio-display', 'no')
  set_option('vo', 'null')
  set_property('volume', '100')
  observe_property('playlist') { |e| @delegate.playlist_changed(e) } if @delegate
  observe_property('pause') { |e| @delegate.pause_changed(e) } if @delegate
  register_event('playback-restart') { |e| @delegate.playback_restart(e) } if @delegate
end

Public Instance Methods

client_name() click to toggle source
# File lib/mpvlib/handle.rb, line 106
def client_name
  MPV.mpv_client_name(@mpv_handle)
end
command(*args) click to toggle source
# File lib/mpvlib/handle.rb, line 119
def command(*args)
  MPV::Error.raise_on_failure("command: args = %p" % args) {
    MPV.mpv_command(@mpv_handle, FFI::MemoryPointer.from_array_of_strings(args.map(&:to_s)))
  }
end
command_async(*args, &block) click to toggle source
# File lib/mpvlib/handle.rb, line 125
def command_async(*args, &block)
  @reply_id += 1
  MPV::Error.raise_on_failure("command_async: args = %p" % args) {
    MPV.mpv_command_async(@mpv_handle, @reply_id, FFI::MemoryPointer.from_array_of_strings(args.map(&:to_s)))
  }
  @property_observers[@reply_id] = block
  @reply_id
end
event_loop(timeout: nil) click to toggle source
# File lib/mpvlib/handle.rb, line 165
def event_loop(timeout: nil)
  loop do
    event = wait_event(timeout: timeout)
    break if event.kind_of?(MPV::Event::None)
    raise event.error if event.error
    if event.reply_id && event.reply_id != 0 && (observer = @property_observers[event.reply_id])
      observer.call(event)
    end
    if (observers = @event_observers[event.event_id])
      observers.each { |o| o.call(event) }
    end
  end
end
get_property(name) click to toggle source
# File lib/mpvlib/handle.rb, line 141
def get_property(name)
  #FIXME: allow non-string values
  MPV.mpv_get_property_string(@mpv_handle, name)
end
get_time_us() click to toggle source
# File lib/mpvlib/handle.rb, line 110
def get_time_us
  MPV.mpv_get_time_us(@mpv_handle)
end
handle_log_message(log_message) click to toggle source
# File lib/mpvlib/handle.rb, line 280
def handle_log_message(log_message)
  if @delegate
    @delegate.add_log_message(
      MPVLogMessageLevels[log_message.level] || Logger::UNKNOWN,
      '%15s: %s' % [log_message.prefix, log_message.text.chomp],
      'MPV')
  end
end
loadlist(path) click to toggle source
# File lib/mpvlib/handle.rb, line 211
def loadlist(path)
  command('loadlist', path.to_s)
end
observe_property(name, &block) click to toggle source
# File lib/mpvlib/handle.rb, line 146
def observe_property(name, &block)
  @reply_id += 1
  MPV::Error.raise_on_failure("set_property: name = %p" % name) {
    MPV.mpv_observe_property(@mpv_handle, @reply_id, name, :MPV_FORMAT_STRING)
  }
  @property_observers[@reply_id] = block
  @reply_id
end
pause() click to toggle source
# File lib/mpvlib/handle.rb, line 223
def pause
  case get_property('pause')
  when 'no', nil
    false
  when 'yes'
    true
  end
end
pause=(state) click to toggle source
# File lib/mpvlib/handle.rb, line 232
def pause=(state)
  set_property('pause', state ? 'yes' : 'no')
end
play(playlist=nil) click to toggle source
# File lib/mpvlib/handle.rb, line 256
def play(playlist=nil)
  if playlist
    @playlist_file.dirname.mkpath
    @playlist_file.open('w') do |io|
      playlist.each { |p|
        raise "Track in playlist not defined or nonexistant: #{p.inspect}" unless p && p.exist?
        io.puts(p)
      }
    end
  end
  loadlist(@playlist_file)
end
playlist() click to toggle source
# File lib/mpvlib/handle.rb, line 252
def playlist
  JSON.parse(get_property('playlist')).map { |h| HashStruct.new(h) }
end
playlist_count() click to toggle source
# File lib/mpvlib/handle.rb, line 199
def playlist_count
  (v = get_property('playlist/count')) && v.to_i
end
playlist_filename(position) click to toggle source
# File lib/mpvlib/handle.rb, line 244
def playlist_filename(position)
  if (filename = get_property("playlist/#{position}/filename")) && !filename.empty?
    Path.new(filename)
  else
    nil
  end
end
playlist_next() click to toggle source
# File lib/mpvlib/handle.rb, line 219
def playlist_next
  command('playlist-next')
end
playlist_position() click to toggle source
# File lib/mpvlib/handle.rb, line 191
def playlist_position
  (v = get_property('playlist-pos')) && v.to_i
end
playlist_position=(position) click to toggle source
# File lib/mpvlib/handle.rb, line 195
def playlist_position=(position)
  set_property('playlist-pos', position)
end
playlist_previous() click to toggle source
# File lib/mpvlib/handle.rb, line 215
def playlist_previous
  command('playlist-prev')
end
register_event(name, &block) click to toggle source
# File lib/mpvlib/handle.rb, line 155
def register_event(name, &block)
  event_id = MPVEventNames[name] or raise "No such event: #{name.inspect}"
  @event_observers[event_id] ||= []
  @event_observers[event_id] << block
end
request_log_messages(level, &block) click to toggle source
# File lib/mpvlib/handle.rb, line 184
def request_log_messages(level, &block)
  MPV::Error.raise_on_failure("request_log_messages: level = %p" % level) {
    MPV.mpv_request_log_messages(@mpv_handle, level)
  }
  register_event('log-message', &block) if block_given?
end
run_event_loop() click to toggle source
# File lib/mpvlib/handle.rb, line 179
def run_event_loop
  @wakeup_pipe.read_nonblock(1024)
  event_loop(timeout: 0)
end
seek_by(seconds) click to toggle source
# File lib/mpvlib/handle.rb, line 236
def seek_by(seconds)
  command('seek', seconds)
end
seek_to_percent(percent) click to toggle source
# File lib/mpvlib/handle.rb, line 240
def seek_to_percent(percent)
  command('seek', percent, 'absolute-percent')
end
set_option(name, value) click to toggle source
# File lib/mpvlib/handle.rb, line 114
def set_option(name, value)
  #FIXME: allow non-string values
  MPV.mpv_set_option_string(@mpv_handle, name, value.to_s)
end
set_property(name, data) click to toggle source
# File lib/mpvlib/handle.rb, line 134
def set_property(name, data)
  #FIXME: allow non-string values
  MPV::Error.raise_on_failure("set_property: name = %p, data = %p" % [name, data]) {
    MPV.mpv_set_property_string(@mpv_handle, name, data.to_s)
  }
end
time_position() click to toggle source
# File lib/mpvlib/handle.rb, line 203
def time_position
  (v = get_property('time-pos')) && v.to_f
end
time_position=(position) click to toggle source
# File lib/mpvlib/handle.rb, line 207
def time_position=(position)
  set_property('time-pos', position)
end
wait_event(timeout: nil) click to toggle source
# File lib/mpvlib/handle.rb, line 161
def wait_event(timeout: nil)
  Event.new_from_mpv_event(MPV.mpv_wait_event(@mpv_handle, timeout || -1))
end