Skip to content

Instantly share code, notes, and snippets.

@pyro2927
Created March 8, 2012 15:44
Show Gist options
  • Save pyro2927/2001583 to your computer and use it in GitHub Desktop.
Save pyro2927/2001583 to your computer and use it in GitHub Desktop.
threaded ruby script to run VLC sync
# setup static variables
MOVIE_FOLDER = "/Volumes/DroboFS/tdb103170485/2/Public/Movies/"
#help output
# +----[ Remote control commands ]
# |
# | add XYZ . . . . . . . . . . . . add XYZ to playlist
# | enqueue XYZ . . . . . . . . . queue XYZ to playlist
# | playlist . . . . . show items currently in playlist
# | play . . . . . . . . . . . . . . . . . . play stream
# | stop . . . . . . . . . . . . . . . . . . stop stream
# | next . . . . . . . . . . . . . . next playlist item
# | prev . . . . . . . . . . . . previous playlist item
# | goto . . . . . . . . . . . . . . goto item at index
# | repeat [on|off] . . . . toggle playlist item repeat
# | loop [on|off] . . . . . . . . . toggle playlist loop
# | random [on|off] . . . . . . . toggle random jumping
# | clear . . . . . . . . . . . . . . clear the playlist
# | status . . . . . . . . . . . current playlist status
# | title [X] . . . . . . set/get title in current item
# | title_n . . . . . . . . next title in current item
# | title_p . . . . . . previous title in current item
# | chapter [X] . . . . set/get chapter in current item
# | chapter_n . . . . . . next chapter in current item
# | chapter_p . . . . previous chapter in current item
# |
# | seek X . . . seek in seconds, for instance `seek 12'
# | pause . . . . . . . . . . . . . . . . toggle pause
# | fastforward . . . . . . . . . set to maximum rate
# | rewind . . . . . . . . . . . . set to minimum rate
# | faster . . . . . . . . . . faster playing of stream
# | slower . . . . . . . . . . slower playing of stream
# | normal . . . . . . . . . . normal playing of stream
# | frame. . . . . . . . . . play frame by frame
# | f [on|off] . . . . . . . . . . . . toggle fullscreen
# | info . . . . . information about the current stream
# | stats . . . . . . . . show statistical information
# | get_time . . seconds elapsed since stream's beginning
# | is_playing . . . . 1 if a stream plays, 0 otherwise
# | get_title . . . . . the title of the current stream
# | get_length . . . . the length of the current stream
# |
# | volume [X] . . . . . . . . . . set/get audio volume
# | volup [X] . . . . . . . raise audio volume X steps
# | voldown [X] . . . . . . lower audio volume X steps
# | adev [X] . . . . . . . . . . . set/get audio device
# | achan [X]. . . . . . . . . . set/get audio channels
# | atrack [X] . . . . . . . . . . . set/get audio track
# | vtrack [X] . . . . . . . . . . . set/get video track
# | vratio [X] . . . . . . . set/get video aspect ratio
# | vcrop [X] . . . . . . . . . . . set/get video crop
# | vzoom [X] . . . . . . . . . . . set/get video zoom
# | snapshot . . . . . . . . . . . . take video snapshot
# | strack [X] . . . . . . . . . set/get subtitles track
# | key [hotkey name] . . . . . . simulate hotkey press
# | menu . . [on|off|up|down|left|right|select] use menu
# |
# | help . . . . . . . . . . . . . . . this help message
# | longhelp . . . . . . . . . . . a longer help message
# | logout . . . . . . . exit (if in socket connection)
# | quit . . . . . . . . . . . . . . . . . . . quit vlc
# |
# +----[ end of help ]
# start script
require 'socket'
require 'timeout'
server = TCPServer.open(2300)
# Setup our clients
$clientArray = Array.new
def sendCommand(command, clientHash)
# %x[echo #{command} | nc #{clientHash[:ip]} #{clientHash[:port]}]
puts "Running command '#{command}' on client #{clientHash[:ip]}"
clientHash[:socket].puts(command)
readSocket(clientHash[:socket])
end
def sendAllCommand(command)
# puts "Running command '#{command}' on all clients"
$clientArray.each do |clientHash|
sendCommand(command, clientHash)
end
end
def readSocket(socket)
begin
#don't let this stall us
begin
timeout (1) do
line = socket.gets
puts line.chomp
end
rescue
return
end
end while true
end
#authenticate against the luarc
def auth(clientHash)
puts "Authenticating"
socket = clientHash[:socket]
#readSocket(socket)
#put in our admin password
socket.puts "admin"
readSocket(socket)
puts "Done authenticating"
end
loop { # Servers run forever
Thread.start(server.accept) do |client|
#loop over commands from the client
loop {
line = client.gets
line.chomp!
args = line.split(" ")
case args[0]
# help text
when "help"
client.puts "To start, open VLC and select VLC > Add Interface > Telnet'\nThen run 'register 4212' here to register your client for syncronized playback"
client.puts "** Commands **"
client.puts "* register <port> (registers a vlc oldrc port with this server)"
client.puts "* unregister (unregisters all ports from the client's IP)"
client.puts "* seek <number_in_seconds>"
client.puts "* pause (toggles pause on/off)"
client.puts "* startover (starts film over)"
client.puts "* list (list all movies on main server)"
when "list"
client.puts %x[ls #{MOVIE_FOLDER}]
#list clients by ip
when "clients"
$clientArray.each do |clientHash|
client.puts "* #{clientHash[:ip]}"
end
# register this client
when "register"
if args[1].nil?
client.puts "Missing VLC port number"
else
#get our IP address
port, ip = Socket.unpack_sockaddr_in(client.getpeername)
client.puts "Registering client with IP: #{ip}"
vlcSocket = TCPSocket.open(ip, args[1])
$clientArray.push({:ip => ip, :port => args[1], :socket => vlcSocket })
auth($clientArray.last)
end
#remove this client
when "unregister"
#get our IP address
port, ip = Socket.unpack_sockaddr_in(client.getpeername)
$clientArray.delete_if {|hash| hash[:ip] == ip }
client.puts "Client removed, #{ $clientArray.length } remaining clients"
when "play"
client.puts "Playing clients..."
$clientArray.each do |clientHash|
is_playing = sendCommand("is_playing",clientHash)
if is_playing != 1
sendCommand("play",clientHash)
client.puts "Client #{clientHash[:ip]} now playing"
else
client.puts "Client #{clientHash[:ip]} already playing"
end
end
when "pause"
client.puts "Toggling pause on clients..."
sendAllCommand("pause")
when "seek"
if args[1].nil?
client.puts "Need seek time"
else
sendAllCommand("seek #{args[1]}")
end
when "startover"
client.puts "Starting everyone over"
sendAllCommand("stop")
sendAllCommand("play")
sendAllCommand("seek 0")
else
client.puts "Command (#{command})not understood"
end
}
end
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment