Murga-Projects Forums
access to media files on a LAN server - Printable Version

+- Murga-Projects Forums (http://www.murga-projects.com/forum)
+-- Forum: Project Forums (/forumdisplay.php?fid=1)
+--- Forum: MurgaLua - General (/forumdisplay.php?fid=2)
+--- Thread: access to media files on a LAN server (/showthread.php?tid=371)


access to media files on a LAN server - mikshaw - 01-10-2010 01:33 PM

I recently spent a decent amount of time researching ways to stream media over a LAN server, and after wading through many sites talking mostly about Flash and other heavy options I eventually learned that some of the media players we all have installed already support streaming directly from a regular http/ftp link. For a few days I was playing around with mplayer and VLC, and it always came down to having to either copy and paste URLs or use a playlist that automatically starts playing.

So i decided to make a script that would bypass the need for a browser just to get a link and just run your chosen media player when you found what you wanted.

Note that this might not be suitable in any situation other than what I use it for, which is a local network, and it hasn't been tested for problems that might arise as a result of the server or any of the desired files being unavailable. Also note that it was written specifically to access one file at a time (i.e. a movie), not a playlist, and it DOES NOT SUPPORT SUBDIRECTORIES beyond what is listed in url[#] at this time. Subdirectories might actually break it, though so far they just seem to create a blank browser.

Requires a file host.."/lua_menu" which contains commands that add data to two tables, label and url. The format is:
label[1]="this is a label for dir 1"; url[1]="/this/is/the/dir/where/label1/files/live"
The URL must be a directory containing regular media files only (at this point), and if the host variable doesn't end with a slash, url must begin with a slash (url begins where host leaves off).

As always, bug reports and suggestions are welcome. I know I do sloppy work with tables, so if something better is suggested (while not making lua_menu more complicated to edit) I'd like that.

On a side note, it appears that Windows opens a cmd window when os.execute() is run. Is this because I used Progra~1 instead of trying harder to use the real path, or does that always happen with os.execute()?

Yet another note: the "srt" exception was added because I have some movies with srt subtitles...they work when I play the movies locally, but they serve no purpose when accessed through the network....one of these days I'm going to find out about serving subtitle files.

Code:
-- USER CONFIGURATION

--player="C:\\Progra~1\\SMPlayer\\smplayer.exe" -- Windows
player="mplayer" -- Linux
host="http://myhost/videos"

-- END USER CONFIGURATION

label={}; url={}
-- retrieve the menu from server
menufile,c,h=socket.http.request(host.."/lua_menu")
assert(loadstring(menufile))()

function get_menu()
box:clear()
for i,v in pairs(label) do
  box:add(v)
end
menu_up=1
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=\"(.-)\"") do
  if not string.find(l,"\.srt$") and not string.find(l,"\/") then
  box:add(l)
  end
end
menu_up=0
end

function play()
if box:value() > 0 and menu_up==0 then
  win:hide()
  Fl:check()
  os.execute(player.." "..dir.."/"..box:text(box:value()))
--  os.exit()
  win:show()
end
end

function menu_choice()
if box:value() > 0  and menu_up==1 then
dir=host..url[box:value()]
get_files()
end
end

ww,wh,bh=420,400,25
bw=ww/3
win=fltk:Fl_Window(ww,wh,"Movies")
box=fltk:Fl_Hold_Browser(0,0,ww,wh-bh); box:callback(menu_choice)
go=fltk:Fl_Button(0,wh-bh,bw,bh,"play"); go:callback(play)
fresh=fltk:Fl_Button(bw,wh-bh,bw,bh,"menu"); fresh:callback(get_menu)
no=fltk:Fl_Button(bw*2,wh-bh,bw,bh,"quit"); no:callback(function() os.exit() end)

--table.sort(menu)
get_menu()

--win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - mikshaw - 01-10-2010 02:55 PM

Also have to fix the keyboard control, but that's usually done after the clicky interface is fairly stable.


RE: access to media files on a LAN server - mikshaw - 01-12-2010 03:01 PM

Did some fixin'
Keyboard control should be halfway decent now.
The menu file is flexible, but i don't know if that is actually helpful.
Access is granted via double-click rather than having to click to select and then click a button to play.

EDIT: fixed crash if menu_file is not getted.
Still want to look into supporting subdirectories, but it feels complicated at the moment.

Code:
#!/usr/bin/env murgaLua

-- access media files on a file server & stream in a player
-- mikshaw 2010

--> USER CONFIGURATION <--

--player="C:\\Progra~1\\SMPlayer\\smplayer.exe" -- Windows
player="mplayer" -- Linux
host="http://localhost/videos"
menu_file=host.."/lua_menu"

--> END USER CONFIGURATION <--

label={}; url={}
-- retrieve the menu from server
menufile,c,h=socket.http.request(menu_file)
if c~=200 then
fltk.fl_alert("could not find "..menu_file)
os.exit() end
assert(loadstring(menufile))()

function get_menu()
box:clear()
for i,v in pairs(label) do
  box:add(v)
end
fresh:deactivate()
go:label("Show files")
box:value(1)
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=\"(.-)\"") do
  if not string.find(l,"\.srt$") and not string.find(l,"\/") then
  box:add(l)
  end
end
fresh:activate()
go:label("Play")
box:value(1)
end

function play(self)
if box:value() > 0 then
  if self:label()=="Play" then
    win:hide()
    Fl:check()
    os.execute(player.." "..dir.."/"..box:text(box:value()))
--    os.exit()
    win:show()
  else
    dir=host..url[box:value()]
    get_files()
  end
end
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
go:do_callback()
end
end

ww,wh,bh=420,400,25
bw=ww/3
win=fltk:Fl_Window(ww,wh,"Movies")
box=fltk:Fl_Hold_Browser(0,0,ww,wh-bh); box:callback(dubbleclik)
go=fltk:Fl_Return_Button(0,wh-bh,bw,bh,"Play"); go:callback(play)
fresh=fltk:Fl_Button(bw,wh-bh,bw,bh,"&Menu"); fresh:callback(get_menu)
no=fltk:Fl_Button(bw*2,wh-bh,bw,bh,"&Quit"); no:callback(function() os.exit() end)

--table.sort(menu)
get_menu()

--win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - JohnMurga - 01-14-2010 08:01 PM

Sorry, just saw this now, I've been away.

I'll test tonight.

Regarding SRT files ... I don't think there is a way to serve them over the network.

The only solution I found is to do realtime transcoding, which is a bit like using a bulldozer to kill an ant.

Not sure about OS.execute(), but sys.spawn() doesn't open a CMD window.

Cheers
John de Murga


RE: access to media files on a LAN server - mikshaw - 01-15-2010 05:13 AM

re: sys.spawn
Looks like it will work fine, but I don't really understand it.
At this point, what I see is
sys.spawn(command,{command_arguments?},something,something,something) =o)

I'm curious how one learns to use a software that has no website or documentation =o\

Anyway, this seems to be working for my current project:
sys.spawn(player, {dir.."/"..box:text(box:value())})
I still don't know when it's appropriate to use assert(), although the example used it.

But now I have to figure out how to keep the murgaLua window hidden while the player runs, since it apparently backgrounds the process by default. Maybe that's where one of the "something" parameters comes in?
I would use iconize() rather than hide(), but my window manager does not support minimizing.
Then again, over 99% of the world's desktop computer users do not have this issue, so maybe I should just go with iconize() and only use hide() for my personal copy.


RE: access to media files on a LAN server - JohnMurga - 01-16-2010 09:04 AM

mikshaw Wrote:
I'm curious how one learns to use a software that has no website or documentation =o\

Natural reaction, I am sorry.

Thats why I don't want to release a full murgaLua release until I get chance to have half decent documentation that goes with it.

I'll look at my docs snapshot as I think I did that function already.

Cheers
JohnM


RE: access to media files on a LAN server - mikshaw - 01-16-2010 01:48 PM

That's a reasonable reason to not release a public release.
However, even though you don't have thorough documentation right now you do have this website, complete with a forum where people can get support from other users when they have questions. When I clicked the luasys "project home page" link at LuaForge, there was an index.php file listed as part of a directory listing...pretty much useless when the server apparently doesn't recognize index.php as a default index page, especially considering that I looked into the php page and saw nothing that had anything to do with luasys.


RE: access to media files on a LAN server - JohnMurga - 01-17-2010 12:42 PM

That another thing, I have to upgrade the forum so that people can register themselves ...
(Obviously with a good anti spam system).

Anyway ... The parameters for sys.spawn are :

Code:
filename (string),
arguments (table: {number => string}),
pid_udata (of new process),
in (fd_udata), out (fd_udata), err (fd_udata),
is_console (boolean)


For what you are doing sys.run might work too :-)

Cheers
JohnM


RE: access to media files on a LAN server - mikshaw - 01-18-2010 03:32 PM

Ok, thanks, I'll try that. I noticed that using sys.spawn as I previously posted was causing murgaLua to crash after a series of 1) running the spawn command, 2) stopping the command, and then 3) sending an event to the murgaLua window. For now I've gone back to os.execute()

I did a bit of a rewrite to the original script today, although it's a little buggy. I dumped the menu file in favor of a couple of main menu items set within the script. I had made the menu file originally just because my videos directory already had an index.html file in its root for the lan website, but that file was a bit of a pain to parse in Lua. Now since this script is a more convenient way to play the files than by using a web browser, I got rid of the index.html file so all directories behave the same...just have to grab the "<a href=" strings.

The bugs come from not-fully-worked-out subdirectory support. At this point it looks like it's mostly working, with the browser hopefully keeping track of which item in the previous directory was selected...but I haven't tested it enough to know how reliable it is.

Code:
#!/usr/bin/env murgaLua

-- access media files on a file server & stream in a player
-- mikshaw 2010

--player="C:\\Progra~1\\SMPlayer\\smplayer.exe" -- Windows
player="mplayer" -- Linux
host="http://localhost"


ext= { "mp3", "ogg", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "asf", "mpg", "mpeg", "wmv", "wav" }

function get_menu()
box:clear()
box:add("videos/")
box:add("mp3/")
level=0
box:value(1)
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=\"(.-)\"") do
  if string.find(l,"\/$") then box:add(l) end
  for k,v in pairs(ext) do
    if string.find(string.lower(l),"%."..v) then
      box:add(l)
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
--print(pos[level],dir)
end

function play()
win:hide()
Fl:check()
--sys.spawn(player,{dir.."/"..box:text(box:value())}) --crashes
os.execute(player.." "..dir.."/"..box:text(box:value()))
win:show()
end

function go_back()
--pos[level]=box:value()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
--pos[level]=box:value()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end


ww,wh,bh=420,400,25
bw=ww/3
win=fltk:Fl_Window(ww,wh,"Movies")
box=fltk:Fl_Hold_Browser(0,0,ww,wh-bh); box:callback(dubbleclik)
pack=fltk.Fl_Pack(0,wh-bh,wh,bh)
pack:type(1)
go=fltk:Fl_Return_Button(0,0,bw,bh,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,0,bw,bh,"&Menu"); fresh:callback(get_menu)
no=fltk:Fl_Button(0,0,bw,bh,"&Quit"); no:callback(function() os.exit() end)
fltk:Fl_End()

pos={}
pos[0]=1
dir=host
get_menu()

--win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - mikshaw - 01-19-2010 04:25 AM

I think I fixed the navigation glitches.
Also now displays file size, although it is dependent upon having a server directory listing that puts the filesize in a <td class="s"> tag, since I couldn't think of another way to parse it. For now I'm just hoping it's not specific to lighttpd, but I may need to find a better way to do it.
EDIT: It appears that Apache doesn't use tables for directory listings, so I'm definitely going to need a new solution for file sizes. Seems to have been easier than I thought:
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1")
I wouldn't be surprised if this is still not universal, but it will at least work for more than just lighttpd servers.

I moved the buttons off the visible interface, since there is already keyboard and double-click behavior to handle the same tasks as clicking the buttons.

EDIT2: fixed the ext loop to search for the extension at the end of the string, and to break if it matches.

EDIT3: It seems that having the main menu being dictated by the script is silly, when the server can easily just set up a "media" directory. Please bear with me...I'm not an expert with web servers, and things are likely to change a lot from week to week =o)
It's now set up so that there is a plain directory structure starting with "host", and what the server wants to do from that point is the server's problem.

Code:
#!/usr/bin/env murgaLua

-- access media files on a file server & stream in a player
-- mikshaw 2010

--player="C:\\Progra~1\\SMPlayer\\smplayer.exe" -- Windows
player="mplayer" -- Linux
host="http://localhost/media"


ext= { "mp3", "ogg", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "asf", "mpg", "mpeg", "wmv", "wav" }

function get_menu()
--box:clear()
--box:add("video/")
--box:add("audio/")
level=0
dir=host
get_files()
box:remove(1) -- get rid of the ../
while pos[1] do table.remove(pos) end
box:value(pos[level])
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=.-\n") do
filename=string.gsub(l,"<a href=\"(.-)\".*","%1")
--filesize=string.gsub(l,".*<td class=\"s\">(.-)</td>.*","%1")
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1")
  if string.find(filename,"\/$") then box:add(filename) end
  for k,v in pairs(ext) do
    if string.find(string.lower(filename),"%."..v.."$") then
      box:add(filename.."\t"..filesize)
      break
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
end

function play()
win:hide()
Fl:check()
--sys.spawn(player,{dir.."/"..box:text(box:value())}) --crashes
os.execute(player.." "..dir.."/"..string.gsub(box:text(box:value()),"\t.*",""))
win:show()
end

function go_back()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end


ww,wh,bh=550,400,25
bw=ww/3
win=fltk:Fl_Double_Window(ww,wh,"Movies")
box=fltk:Fl_Hold_Browser(0,0,ww,wh); box:callback(dubbleclik)
box:column_widths({ww-100,100,0})
pack=fltk.Fl_Pack(0,wh,wh,bh)
pack:type(1)
go=fltk:Fl_Return_Button(0,0,bw,bh,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,0,bw,bh,"&Menu"); fresh:callback(get_menu)
no=fltk:Fl_Button(0,0,bw,bh,"&Quit"); no:callback(function() os.exit() end)
fltk:Fl_End()

pos={}
pos[0]=1
get_menu()

win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - mikshaw - 02-01-2010 07:05 AM

I believe I've come up with a kludge for serving subtitles, although my current idea might work only for mplayer, and I'm dealing only with *.srt for now. I don't yet know anything about how another player might specify a subtitle file as part of the command. I might need to create a separate user-configurable variable for that.

Anyway, what I'm thinking (still thinking about it as I type, so nothing's been coded yet) is to create a subtitle filename string by replacing the filename extension with ".srt" and search body for that string. If it's found, then do another http.request for that subtitle file, write the string returned by that request to a tempfile, and use that tempfile as part of the mplayer command. This would be done at the start of the play function.

If it works for me I'll post the initial code, and then do some research on how other media players handle subtitles on the commandline.


RE: access to media files on a LAN server - mikshaw - 02-01-2010 08:10 AM

This one works with mplayer, and probably smplayer.
For VLC, subflag=" --sub="..subtmp.." " should work.
In Media player Classic, apparently use subflag=" /sub "..subtmp.." " (might need extra quotes around the filename?)
I don't think Windows Media Player will work.

Code:
#!/usr/bin/env murgaLua

-- access media files on a file server & stream in a player
-- mikshaw 2010

--player="C:\\Progra~1\\SMPlayer\\smplayer.exe" -- Windows
player="mplayer" -- Linux
host="http://localhost/media"


ext= { "mp3", "ogg", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "asf", "mpg", "mpeg", "wmv", "wav" }

subtmp=os.tmpname()

function get_menu()
level=0
dir=host
get_files()
box:remove(1) -- get rid of the ../
while pos[1] do table.remove(pos) end
box:value(pos[level])
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=.-\n") do
filename=string.gsub(l,"<a href=\"(.-)\".*","%1")
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1")
  if string.find(filename,"\/$") then box:add(filename) end
  for k,v in pairs(ext) do
    if string.find(string.lower(filename),"%."..v.."$") then
      box:add(filename.."\t"..filesize)
      break
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
end

function play()
realfile=string.gsub(box:text(box:value()),"\t.*","")
subfile=string.gsub(realfile,"%.%w-$","%.srt")
if string.find(body,"<a href=\""..subfile.."\"") then
subdata,y,z=socket.http.request(dir.."/"..subfile)
my_filename=io.open(subtmp,"w")
if my_filename then
  my_filename:write(subdata)
  my_filename:close()
end
subflag=" -sub "..subtmp.." "
else subflag=" "
end
win:iconize()
Fl:check()
os.execute(player..subflag..dir.."/"..realfile)
end

function go_back()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end

function quit()
os.remove(subtmp)
os.exit()
end

ww,wh,bh=550,400,25
bw=ww/3
win=fltk:Fl_Double_Window(ww,wh,"Movies")
win:callback(quit)
box=fltk:Fl_Hold_Browser(0,0,ww,wh); box:callback(dubbleclik)
box:column_widths({ww-100,100,0})
pack=fltk.Fl_Pack(0,wh,wh,bh)
pack:type(1)
go=fltk:Fl_Return_Button(0,0,bw,bh,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,0,bw,bh,"&Menu"); fresh:callback(get_menu)
fltk:Fl_End()

pos={}
pos[0]=1
get_menu()

win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - mikshaw - 04-03-2010 11:57 PM

The subtitle feature seems to be a little flaky on Windows smplayer, don't know about Mac. I have two movies that include *.srt files; both work on Linux mplayer, but one works on Windows smplayer.

The current version allows for an optional configuration file, so you can change the player and host once and not have to do it again every time the script is updated. The file's format is lua variables (the file is parsed as a lua chunk).

The current available identifiers are player, subtitle_flag, and host.
I have not found a way yet in Windows to use the standard path name (including stupid spaces) for player, so I'm using "Progra~1\\...." (also note the escaped backslash).
The subtitle_flag variable only comes into play when srt files are found, and it might not work as currently scripted for a player that uses the "flag=value" format. The whole subtitle feature is a bit messy at this time. It will probably cause problems with some players.
The host variable is a URL pointing to the directory containing the server's media files, not including the trailing slash (though I don't yet know how a trailing slash might affect the script).

Note, as I probably said before, that even little changes in the way a server indexes directories might determine whether or not this script fails. I have tried to improve that part a bit, but i'm sure it's far from perfect.

This version also adds an update feature. The way this feature works will probably seem strange (updates are retrieved from your own server), but it was added only so that I could more easily update the same script on two different OSs for testing. It does not get updates from the internet.

Code:
#!/usr/bin/env murgaLua

-- access media files on a file server & stream in a player
-- mikshaw 2010

local VERSION=3

-- check for configuration file
local myos,cfg=murgaLua.getHostOsName()
if myos=="windows" then cfg=os.getenv("USERPROFILE").."\\media.lua.cfg"
else cfg=os.getenv("HOME").."/.media.lua.cfg" end
local get_cfg=loadfile(cfg)
if get_cfg then get_cfg() end

-- apply configuration variables
if myos=="windows" then
player=player or "C:\\Progra~1\\SMPlayer\\smplayer.exe"
else
player=player or "mplayer"
end
subtitle_flag=subtitle_flag or "-sub"
host=host or "http://192.168.1.101/media"

function update_me()
local remote_file=host.."/media.lua"
local body,code,header=socket.http.request(remote_file)
if code~=200 then fltk.fl_alert("I couldn't check for updates for some reason.\nNo biggie.")
return end
local current_version=tonumber(string.match(body,"VERSION=([%d]*)"))
if current_version > VERSION then
  local ask=fltk.fl_choice("There is a newer version available.\nDo you want to update?","no","yes",NULL)
  if ask==1 then
    local outpoot=io.open(arg[0],"w")
    if outpoot then
      outpoot:write(body)
      outpoot:close()
      fltk.fl_message("Update successful.\nPlease restart the program.")
    else fltk.fl_alert("Sorry, but I couldn't update your script.\n You can try to download it yourself at "..remote_file) end
  end
else fltk.fl_message("You have the latest version.") end
end

ext= { "mp3", "ogg", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "asf", "mpg", "mpeg", "wmv", "wav" }

subtmp=os.tmpname()

function get_menu()
level=0
dir=host
get_files()
box:remove(1) -- get rid of the ../
while pos[1] do table.remove(pos) end
box:value(pos[level])
end

function get_files()
box:clear()
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=.-\n") do
filename=string.gsub(l,"<a href=\"(.-)\".*","%1")
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1")
  if string.find(filename,"\/$") then box:add(filename) end
  for k,v in pairs(ext) do
    if string.find(string.lower(filename),"%."..v.."$") then
      box:add(filename.."\t"..filesize)
      break
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
end

function play()
realfile=string.gsub(box:text(box:value()),"\t.*","")
subfile=string.gsub(realfile,"%.%w-$","%.srt")
if string.find(body,"<a href=\""..subfile.."\"") then
subdata,y,z=socket.http.request(dir.."/"..subfile)
my_filename=io.open(subtmp,"w")
if my_filename then
  my_filename:write(subdata)
  my_filename:close()
end
subflag=" "..subtitle_flag.." "..subtmp.." "
else subflag=" "
end
win:iconize()
Fl:check()
os.execute(player..subflag..dir.."/"..realfile)
win:show()
end

function go_back()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end

function quit()
os.remove(subtmp)
os.exit()
end

ww,wh,bh=550,400,25
win=fltk:Fl_Double_Window(ww,wh,"Movies")
win:callback(quit)
box=fltk:Fl_Hold_Browser(0,0,ww,wh); box:callback(dubbleclik)
box:column_widths({ww-100,100,0})
go=fltk:Fl_Return_Button(0,0,0,0,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,0,0,0,"&Menu"); fresh:callback(get_menu)
update=fltk:Fl_Button(0,0,0,0,"&Update"); update:callback(update_me)

pos={}
pos[0]=1
get_menu()

win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - iGame3D - 04-06-2010 06:15 AM

I changed the host to myself and this to get it to work on Mac with VLC player.

Code:
-- apply configuration variables
if myos=="windows" then
player=player or "C:\\Progra~1\\SMPlayer\\smplayer.exe"
elseif myos=="macos" then player=player or  "/Applications/VLC.app/Contents/MacOS/VLC"
else
player=player or  "mplayer"
end


Works ok.
But gets stuck after playing each movie for a very long time.
Is ox.execute() blocking?


RE: access to media files on a LAN server - mikshaw - 04-07-2010 04:25 AM

I'm not sure what you mean by blocking. In its current state it does prevent access to the murgaLua interface while the player is running....don't know if the player on mac is remaining open after the file is finished? If so, adding "&" at the end of the execute string might help (I don't think this works on windows).

I'm planning eventually to work out my trouble with sys.spawn to replace os.execute, so maybe that will help too.

The most recent version posted supports a config file ($HOME/.media.lua.cfg) where you can set the player variable, so you don't really need to change the script to do this, but I'll include the macos default in the next version. Is that path you're using a common one on mac? Also, does VLC on Mac use the --sub=filename option, or something else?


RE: access to media files on a LAN server - iGame3D - 04-08-2010 02:25 PM

mikshaw Wrote:
I'm not sure what you mean by blocking.

Parent program ignores input and updates Ëœuntil child returns/exits.

mikshaw Wrote:
If so, adding "&" at the end of the execute string might help

The what line where now?

mikshaw Wrote:
Is that path you're using a common one on mac?


/Applications/
is the standard install directory.

Most applications are self contained, ie, VLC.app is technically a folder:
/Applications/VLC.app/

Binary executable have a standard location in that path:
/Contents/MacOS/VLC

Double clicking the 'folder' executes the binary and it knows where all its required elements are.

Quicktime.app would be the standard media player..or ..iTunes.app

mikshaw Wrote:
[quote]
Also, does VLC on Mac use the --sub=filename option, or something else?


I have no idea, really.
But here some links:
VLC command line index online
VLC on Mac OS X


RE: access to media files on a LAN server - mikshaw - 04-09-2010 12:02 AM

Quote:
The what line where now?

In function play(), the os.execute line:
os.execute(player..subflag..dir.."/"..realfile.." &")
Adding an ampersand to the end of the command (in Linux/UNIX/OSX) runs the command in the background, detaching the player process from the script process and allowing interaction with the GUI even while the movie plays. I don't know if this is the issue, though.


RE: access to media files on a LAN server - iGame3D - 04-13-2010 10:18 AM

Ah yes that made it work much better. Perfect.


RE: access to media files on a LAN server - mikshaw - 12-29-2010 01:40 AM

Some changes/improvements...
* Moved the temp files into user directory...it seems Vista was having trouble writing to the files when using os.tmpname().
* Added checks to see if the server and media directory are available (separated host and mediadir variables to accomplish this).
* Added a "Play all" button to create and play a temporary playlist of all files in the current directory.
* Fixed the subtitle bug...filenames with dashes were being misinterpreted by string.find().
* Now using ltn12.sink.file() to write subtitle file to local directory.

Code:
#!/usr/bin/env murgaLua

-- access media files on a http server & stream in a player
-- mikshaw 2010

local VERSION=5

-- check for configuration file
myos=murgaLua.getHostOsName()
if myos=="windows" then cfg=os.getenv("USERPROFILE").."\\media.lua.cfg"
else cfg=os.getenv("HOME").."/.media.lua.cfg" end
local get_cfg=loadfile(cfg)
if get_cfg then get_cfg() end

-- apply configuration variables
if myos=="windows" then
player=player or "C:\\Progra~1\\SMPlayer\\smplayer.exe"
pls_flag=pls_flag or ""
else
player=player or "mplayer"
pls_flag=pls_flag or "-playlist"
end
subtitle_flag=subtitle_flag or "-sub"
host=host or "192.168.1.99"
mediadir=mediadir or "/media"

-- check is server is available
testy=socket.protect(function()
  local c = socket.connect(host, 80)
  if not c then fltk.fl_alert("server not found!"); os.exit()
  else c:close() end
end)
testy()

host="http://"..host..mediadir
-- check if the media dir is available
local b,c=socket.http.request(host)
if c~=200 then fltk.fl_alert("media not available"); os.exit() end

pls={}
ext= { "mp3", "ogg", "ogv", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "m4v", "asf", "mpg", "mpeg", "wmv", "wav" }

-- os.tmpname() seems to be unreliable, particularly in Vista
if myos=="windows" then
  plstmp=os.getenv("USERPROFILE").."\\media.lua.pls"
  subtmp=os.getenv("USERPROFILE").."\\media.lua.sub"
else
  plstmp=os.getenv("HOME").."/media.lua.pls"
  subtmp=os.getenv("HOME").."/media.lua.sub"
end

function update_me()
local remote_file=host.."/media.lua"
local body,code,header=socket.http.request(remote_file)
if code~=200 then fltk.fl_alert("I couldn't check for updates for some reason.\nNo biggie.")
return end
local current_version=tonumber(string.match(body,"VERSION=([%d]*)"))
if current_version > VERSION then
  local ask=fltk.fl_choice("There is a newer version available.\nDo you want to update?","no","yes",NULL)
  if ask==1 then
    local outpoot=io.open(arg[0],"w")
    if outpoot then
      outpoot:write(body)
      outpoot:close()
      fltk.fl_message("Update successful.\nPlease restart the program.")
    else fltk.fl_alert("Sorry, but I couldn't update your script.\n You can try to download it yourself at "..remote_file) end
  end
else fltk.fl_message("You have the latest version.") end
end

-- "menu" is a misnomer carried over from earlier version...really just resets to root directory
function get_menu()
level=0
dir=host
get_files()
box:remove(1) -- get rid of the ../
while pos[1] do table.remove(pos) end
box:value(pos[level])
end

function get_files()
box:clear()
pls={}
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=.-\n") do
filename=string.gsub(l,"<a href=\"(.-)\".*","%1")
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1") -- server-specific
  if string.find(filename,"\/$") then box:add(filename) end
  for k,v in pairs(ext) do
    if string.find(string.lower(filename),"%."..v.."$") then
      box:add(filename.."\t"..filesize)
      table.insert(pls,dir.."/"..filename)
      break
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
end

function play()
realfile=string.gsub(box:text(box:value()),"\t.*","")
subfile=string.gsub(realfile,"%.%w-$","%.srt")
if string.find(body,subfile,1,1) then
socket.http.request{
url=dir.."/"..subfile,
sink=ltn12.sink.file(io.open(subtmp,"w"))
}
subflag=" "..subtitle_flag.." "..subtmp.." "
else subflag=" "
end
win:hide()
Fl:check()
os.execute(player..subflag..dir.."/"..realfile)
os.remove(subtmp)
win:show()
end

function play_list()
if not pls[1] then return end
local playlist=io.open(plstmp,"w")
if playlist then
  playlist:write("[playlist]\nNumberOfEntries="..table.maxn(pls).."\n")
  for i,v in pairs(pls) do playlist:write("File"..i.."="..v.."\n") end
  playlist:close()
  win:hide()
  Fl:check()
  os.execute(player.." "..pls_flag.." "..plstmp)
  win:show()
else fltk.fl_message("Sorry, but I couldn't write a playlist")
end
end

function go_back()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end

function quit()
os.remove(subtmp)
os.remove(plstmp)
os.exit()
end

ww,wh,bw,bh=640,400,160,25
win=fltk:Fl_Double_Window(ww,wh,"Movies")
win:callback(quit)
box=fltk:Fl_Hold_Browser(0,0,ww,wh-bh); box:callback(dubbleclik)
box:column_widths({ww-bw,bw,0})
go=fltk:Fl_Return_Button(0,0,0,0,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,wh-bh,bw,bh,"back to &Main"); fresh:callback(get_menu)
playall=fltk:Fl_Button(bw,wh-bh,bw,bh,"&Play all"); playall:callback(play_list)
update=fltk:Fl_Button(bw*2,wh-bh,bw,bh,"check for &Updates"); update:callback(update_me)
exit=fltk:Fl_Button(bw*3,wh-bh,bw,bh,"&Quit"); exit:callback(quit)

pos={}
pos[0]=1
get_menu()

win:resizable(box)
win:show()
Fl:run()




RE: access to media files on a LAN server - mikshaw - 03-28-2011 02:34 AM

One bug fix. I just noticed that it chokes on filenames that contain special characters, parentheses for example, so I surrounded the filename with quotes in the play() function. hasn't been tested on Windows.

Code:
#!/usr/bin/env murgaLua

-- access media files on a http server & stream in a player
-- mikshaw 2010-11

local VERSION=6
Fl:get_system_colors()

-- check for configuration file
myos=murgaLua.getHostOsName()
if myos=="windows" then cfg=os.getenv("USERPROFILE").."\\media.lua.cfg"
else cfg=os.getenv("HOME").."/.media.lua.cfg" end
local get_cfg=loadfile(cfg)
if get_cfg then get_cfg() end

-- apply configuration variables
if myos=="windows" then
player=player or "C:\\Progra~1\\SMPlayer\\smplayer.exe"
pls_flag=pls_flag or ""
else
player=player or "mplayer"
pls_flag=pls_flag or "-playlist"
end
subtitle_flag=subtitle_flag or "-sub"
host=host or "192.168.1.99"
mediadir=mediadir or "/media"

-- check is server is available
testy=socket.protect(function()
  local c = socket.connect(host, 80)
  if not c then fltk.fl_alert("server not found!"); os.exit()
  else c:close() end
end)
testy()

host="http://"..host..mediadir
-- check if the media dir is available
local b,c=socket.http.request(host)
if c~=200 then fltk.fl_alert("media not available"); os.exit() end

pls={}
ext= { "mp3", "ogg", "ogv", "flac", "avi", "mp4", "mov", "divx", "flv",
"mkv", "m4v", "asf", "mpg", "mpeg", "wmv", "wav" }

-- os.tmpname() seems to be unreliable, particularly in Vista
if myos=="windows" then
  plstmp=os.getenv("USERPROFILE").."\\media.lua.pls"
  subtmp=os.getenv("USERPROFILE").."\\media.lua.sub"
else
  plstmp=os.getenv("HOME").."/media.lua.pls"
  subtmp=os.getenv("HOME").."/media.lua.sub"
end

function update_me()
local remote_file=host.."/media.lua"
local body,code,header=socket.http.request(remote_file)
if code~=200 then fltk.fl_alert("I couldn't check for updates for some reason.\nNo biggie.")
return end
local current_version=tonumber(string.match(body,"VERSION=([%d]*)"))
if current_version > VERSION then
  local ask=fltk.fl_choice("There is a newer version available.\nDo you want to update?","no","yes",NULL)
  if ask==1 then
    local outpoot=io.open(arg[0],"w")
    if outpoot then
      outpoot:write(body)
      outpoot:close()
      fltk.fl_message("Update successful.\nPlease restart the program.")
    else fltk.fl_alert("Sorry, but I couldn't update your script.\n You can try to download it yourself at "..remote_file) end
  end
else fltk.fl_message("You have the latest version.") end
end

-- "menu" is a misnomer carried over from earlier version...really just resets to root directory
function get_menu()
level=0
dir=host
get_files()
box:remove(1) -- get rid of the ../
while pos[1] do table.remove(pos) end
box:value(pos[level])
end

function get_files()
box:clear()
pls={}
body,code,header=socket.http.request(dir)
for l in string.gmatch(body,"<a href=.-\n") do
filename=string.gsub(l,"<a href=\"(.-)\".*","%1")
filesize=string.gsub(l,".*>([%d%.]-[KMG])<.*","%1") -- server-specific
  if string.find(filename,"\/$") then box:add(filename) end
  for k,v in pairs(ext) do
    if string.find(string.lower(filename),"%."..v.."$") then
      box:add(filename.."\t"..filesize)
      table.insert(pls,dir.."/"..filename)
      break
    end
  end
end
fresh:activate()
if not pos[level] then pos[level]=1 end
box:value(pos[level])
end

function play()
realfile=string.gsub(box:text(box:value()),"\t.*","")
subfile=string.gsub(realfile,"%.%w-$","%.srt")
if string.find(body,subfile,1,1) then
socket.http.request{
url=dir.."/"..subfile,
sink=ltn12.sink.file(io.open(subtmp,"w"))
}
subflag=" "..subtitle_flag.." "..subtmp.." "
else subflag=" "
end
win:hide()
Fl:check()
-- had to add extra quotes...special characters in filename were causing trouble
os.execute(player..subflag.."\""..dir.."/"..realfile.."\"")
os.remove(subtmp)
win:show()
end

function play_list()
if not pls[1] then return end
local playlist=io.open(plstmp,"w")
if playlist then
  playlist:write("[playlist]\nNumberOfEntries="..table.maxn(pls).."\n")
  for i,v in pairs(pls) do playlist:write("File"..i.."="..v.."\n") end
  playlist:close()
  win:hide()
  Fl:check()
  os.execute(player.." "..pls_flag.." "..plstmp)
  win:show()
else fltk.fl_message("Sorry, but I couldn't write a playlist")
end
end

function go_back()
dir=string.gsub(dir,"/[^/]-/$","")
level=level-1
if host==dir then get_menu()
else
get_files()
end
end

function go_forward()
dir=dir.."/"..box:text(box:value())
level=level+1
get_files()
end

function dubbleclik()
if Fl:event() == fltk.FL_RELEASE and Fl:event_clicks() > 0 then
navigate()
end
end

function navigate()
if box:value() > 0 then
pos[level]=box:value()
  if box:text(box:value())=="../" then go_back()
  elseif string.find(box:text(box:value()),"\/$") then go_forward()
  else play() end
end
end

function quit()
os.remove(subtmp)
os.remove(plstmp)
os.exit()
end

ww,wh,bw,bh=640,400,160,25
win=fltk:Fl_Double_Window(ww,wh,"Movies")
win:callback(quit)
box=fltk:Fl_Hold_Browser(0,0,ww,wh-bh); box:callback(dubbleclik)
box:column_widths({ww-bw,bw,0})
go=fltk:Fl_Return_Button(0,0,0,0,"Open"); go:callback(navigate)
fresh=fltk:Fl_Button(0,wh-bh,bw,bh,"back to &Main"); fresh:callback(get_menu)
playall=fltk:Fl_Button(bw,wh-bh,bw,bh,"&Play all"); playall:callback(play_list)
update=fltk:Fl_Button(bw*2,wh-bh,bw,bh,"check for &Updates"); update:callback(update_me)
exit=fltk:Fl_Button(bw*3,wh-bh,bw,bh,"&Quit"); exit:callback(quit)

pos={}
pos[0]=1
get_menu()

win:resizable(box)
win:show()
Fl:run()