27 December, 2009

Embedded MPlayer in Tk

Ok, something a bit more interesting.

I've been using mplayer since 'bout 94 (near as I can recall), it's has been and continues to be my video player of choice. In spite of that, I still learn things now and again. Today was an instance of learning a little something about it I didn't know before.

Mplayer supports a slave mode, this was news to me. In that mode it is geared to receive commands to manipulate the player. The intention is to allow the creation of front-ends which are plentiful for that reason. I found this especially useful in embedding Mplayer into a Tk window and binding Tk controls to the player.

Below is a rough sampling of how it can be done.


#!/usr/bin/tclsh
package require Tk

proc Exit { } {
exit
}

proc Play { } {
upvar #0 playerId playerId
puts $playerId "pause"
}

proc ReadPipe {chan} {
upvar #0 playerId playerId
set d [read $chan]
foreach line [split $d \n] {
set line [string trim $line]
if {[regexp {^\*\*\* screenshot '(.*?)' \*\*\*} $line -> filename]} {
# delay to permit the file to appear
after 250 [list OnScreenshot $filename]
}
}
if {[eof $chan]} {
fileevent $chan readable {}
close $chan
set playerId ""
}
}

proc EmbedPlayer { w } {
upvar #0 fileList fileList
upvar #0 playerId playerId
set cmd mplayer
lappend cmd -slave -vf scale=1540:1050 -wid [winfo id $w] -idle

set pipe [open |$cmd r+]
fconfigure $pipe -blocking 0 -buffering line
fileevent $pipe readable [list ReadPipe $pipe]
set playerId $pipe

puts $playerId "load [lindex $fileList 0]"
set fileList [lrange $fileList 1 end]
}

proc main { { fileList [list]} } {
wm title . "User Interface"
wm protocol . WM_DELETE_WINDOW [list Exit]
wm withdraw .

frame .video -width 1540 -height 800
grid .video -sticky news

frame .controls -width 1540 -height 100
button .play -text "Play" -command Play
grid .play -sticky news

grid rowconfigure . 0 -weight 1
grid columnconfigure . 0 -weight 1


option add *tearOff false
. configure -menu [menu .menu]
.menu add cascade -label File -menu [menu .menu.file]
.menu.file add command -label Exit -command Exit
bind .video {
bind %W
{}
EmbedPlayer %W
}
wm deiconify .
}

#---main---
set fileList $argv
main


I stripped this segment out of a more involved utility I'm working on so it isn't as clean as it could be.

Issue ./mplayerUi and Bobs Your Uncle.

No comments: