Class: MPlayer::Worker

Inherits:
Object
  • Object
show all
Includes:
ColorDebugMessages
Defined in:
lib/easy_mplayer/worker.rb

Overview

:nodoc:all

Defined Under Namespace

Classes: Stream

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(p) ⇒ Worker

Returns a new instance of Worker.



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/easy_mplayer/worker.rb', line 198

def initialize(p)
  @parent  = p
  @pid     = nil
  @streams = Array.new
  @pending = Array.new
  @mutex   = Mutex.new
  @failed  = nil

  @thread_safe_callbacks = @parent.opts[:thread_safe_callbacks]
  @shutdown_in_progress  = false
  
  begin
    info "running mplayer >>> #{cmdline}"
    @io_stdin, @io_stdout, @io_stderr = Open3.popen3(cmdline)
    
    create_stream(:stdout, @io_stdout)
    create_stream(:stderr, @io_stderr)
    send_each_stream :run
  rescue
    raise BadStream, "couldn't create streams to mplayer: #{$!}"
  end
  
  debug "mplayer threads created!"
end

Instance Attribute Details

#ioObject (readonly)

Returns the value of attribute io.



196
197
198
# File 'lib/easy_mplayer/worker.rb', line 196

def io
  @io
end

#parentObject (readonly)

Returns the value of attribute parent.



196
197
198
# File 'lib/easy_mplayer/worker.rb', line 196

def parent
  @parent
end

Instance Method Details

#close_stdinObject



328
329
330
331
# File 'lib/easy_mplayer/worker.rb', line 328

def close_stdin
  @io_stdin.close if @io_stdin and !@io_stdin.closed?
  @io_stdin = nil
end

#cmdline(target = ) ⇒ Object



223
224
225
226
227
228
# File 'lib/easy_mplayer/worker.rb', line 223

def cmdline(target = parent.opts[:path])
  cmd = "#{parent.opts[:program]} -slave "
  cmd += "-wid #{parent.opts[:embed].call} " if parent.opts[:embed]
  cmd += "-playlist " if target=~ /\.m3u$/
  cmd += '"' + target.to_s + '"'
end

#create_stream(type, io) ⇒ Object



278
279
280
281
282
# File 'lib/easy_mplayer/worker.rb', line 278

def create_stream(type, io)
  returning Stream.new(parent, self, type, io) do |stream|
    @streams.push(stream)
  end
end

#dispatch_callbacksObject



246
247
248
249
250
251
252
253
254
255
256
# File 'lib/easy_mplayer/worker.rb', line 246

def dispatch_callbacks
  return unless @thread_safe_callbacks
  list = nil
  lock! do
    list = @pending
    @pending = Array.new
  end
  list.each do |args|
    @parent.callback! args.first, *(args.last)
  end
end

#flag_stream_error(type) ⇒ Object



301
302
303
304
305
# File 'lib/easy_mplayer/worker.rb', line 301

def flag_stream_error(type)
  lock! do
    @failed = type if @failed.nil?
  end
end

#get_positionObject



333
334
335
336
# File 'lib/easy_mplayer/worker.rb', line 333

def get_position
  send_command :get_time_pos
  send_command :get_percent_pos
end

#lock!Object



230
231
232
233
234
# File 'lib/easy_mplayer/worker.rb', line 230

def lock!
  @mutex.synchronize do
    yield
  end
end

#ok?Boolean

Returns:

  • (Boolean)


307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/easy_mplayer/worker.rb', line 307

def ok?
  get_position
  dispatch_callbacks
  err = nil
  lock! do
    err = @failed
  end
  return true if err.nil? and @streams.length > 0

  case err
  when :eof
    info "MPlayer process shut itself down!"
    close_stdin
  when :stderr
    warn "Caugh error message on MPlayer's STDERR"
  when :exception
    warn "Unexpected IO stream failure!"
  end
  shutdown!
end

#queue_callback(args) ⇒ Object



236
237
238
239
240
241
242
243
244
# File 'lib/easy_mplayer/worker.rb', line 236

def queue_callback(args)
  if @thread_safe_callbacks
    lock! do
      @pending.push(args)
    end
  else
    @parent.callback! args.first, *(args.last)
  end
end

#send_command(*args) ⇒ Object



268
269
270
271
272
273
274
275
276
# File 'lib/easy_mplayer/worker.rb', line 268

def send_command(*args)
  cmd = args.join(' ')
  if @io_stdin.nil?
    debug "cannot send \"#{cmd}\" - stdin closed"
  else
    Command.validate! args
    send_to_stdin cmd
  end
end

#send_each_stream(*args) ⇒ Object



284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
# File 'lib/easy_mplayer/worker.rb', line 284

def send_each_stream(*args)
  cmd     = args.shift
  cmd_str = "#{cmd.to_s}(#{args.join(', ')})"
  if @streams.length < 1
    warn "No streams available for \"cmd_str\""
  else
    debug "Sending each stream: #{cmd_str}"
    @streams.each do |stream|
      if stream.respond_to? cmd
        stream.send(cmd, *args)
      else
        raise BadStream, "stream command not valid: #{cmd_str}"
      end
    end
  end
end

#send_to_stdin(str) ⇒ Object



258
259
260
261
262
263
264
265
266
# File 'lib/easy_mplayer/worker.rb', line 258

def send_to_stdin(str)
  begin
    @io_stdin.puts str
  rescue => e
    warn "Couldn't write to mplayer's stdin!"
    warn "error was: #{e}"
    shutdown!
  end
end

#shutdown!Object



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/easy_mplayer/worker.rb', line 343

def shutdown!
  if @shutdown_in_progress
    debug "shutdown already in progress, skipping shutdown call..."
    return
  end
  
  @parent.callback! :pre_shutdown

  # give mplayer it's close signal
  debug "Sending QUIT to mplayer..."
  @shutdown_in_progress = true
  send_command :quit

  # close our side of the IO
  close_stdin
  
  # then wait for the threads to cleanup after themselves
  info "Waiting for worker thread to exit..."
  send_each_stream :kill
  send_each_stream :join
  @streams = Array.new
  info "MPlayer process cleaned up!"
  @parent.callback! :shutdown
end

#startup!Object



338
339
340
341
# File 'lib/easy_mplayer/worker.rb', line 338

def startup!
  send_command :get_time_length
  @parent.callback! :startup
end