diff --git a/CONTROL/control b/CONTROL/control index 265fa06..6e86d51 100644 --- a/CONTROL/control +++ b/CONTROL/control @@ -1,10 +1,11 @@ Package: webif Priority: optional Section: web -Version: 0.5.3 +Version: 0.5.4 Architecture: mipsel Maintainer: af123@hummypkg.org.uk -Depends: mongoose(>=2.11-5),jim,jim-sqlite3,jim-cgi,jim-oo,service-control,busybox(>=1.18.3-1),lsof,epg(>=1.0.2),hmt(>=1.0.4),ssmtp +Depends: mongoose(>=2.11-5),jim(>=0.71-1),jim-sqlite3(>=0.71-1),jim-cgi(>=0.2),jim-oo,service-control,busybox(>=1.18.3-1),lsof,epg(>=1.0.2),hmt(>=1.0.4),ssmtp Replaces: af123-webif Conflicts: af123-webif +Suggests: ffmpeg Description: A web interface for the Humax. In development. diff --git a/var/mongoose/cgi-bin/browse.jim b/var/mongoose/cgi-bin/browse.jim index c12a753..6ae5e2a 100755 --- a/var/mongoose/cgi-bin/browse.jim +++ b/var/mongoose/cgi-bin/browse.jim @@ -7,58 +7,13 @@ puts "Content-Type: text/html" puts "" set ignore {.nts .thm .hmt .hmi} -set standard {.avi .mpg .wmv .mkv} +set include {.ts .avi .mpg .wmv .mkv} cgi_input #cgi_dump -#set _cgi(tsfile) "/media/My Video/Family Guy/2.19._Excellence_in_Broadcasting.ts" -#set _cgi(action) "delete" #set env(REQUEST_URI) '' - -proc tsfile {file bfile {ajax 0}} {{i 0}} { - set ts [ts fetch $file] - if {$ajax == 0} { puts "
" } - puts " - - - $bfile - - " - if {[$ts get definition] eq "HD"} { - puts "" - } else { - puts "" - } - set locked 0 - if {[$ts flag "Locked"] > 0} { - set locked 1 - puts "" - } - - puts " - - - -
- " - if {$ajax == 0} { puts "
" } -} - -proc genfile {file bfile} { - puts " -
- - - $bfile - -
- " -} +#set _cgi(dir) "/media/My Video/Chuggington" proc directory {file bfile} { puts "
" @@ -67,8 +22,8 @@ proc directory {file bfile} { puts "$bfile
" } -proc entry {file {ajax 0}} { - set bfile [lindex [split $file /] end] +proc entry {file} {{i 0}} { + set bfile [file tail $file] if {[string index $bfile 0] == "\025"} { set bfile [string range $bfile 1 end] } @@ -77,94 +32,61 @@ proc entry {file {ajax 0}} { continue } set ext [file extension $file] - if {$ext eq ".ts"} { - tsfile $file $bfile $ajax - continue - } - if {$ext in $::ignore} { continue } - if {$ext in $::standard} { - genfile $file $bfile - continue - } -} + if {$ext in $::ignore || $ext ni $::include} { continue } -if {[dict exists $_cgi tsfile]} { - set file [dict get $_cgi tsfile] - set ts [ts fetch $file] + set base [file rootname $file] - if {[dict exists $_cgi action]} { - switch [dict get $_cgi action] { - entry { - entry $file 1 - } - delete { - if {[$ts delete]} { - puts "Successfully deleted $file." - } else { - puts "Problem deleting $file, [$ts get error]" - } - } - lock { - set action lock - if {[$ts flag "Locked"]} { set action unlock } - if {[$ts $action]} { - puts "Successfully [set action]ed $file." - } else { - puts "Problem [set action]ing $file, - [$ts get error]" - } - } - } - exit + if {$ext eq ".ts" && [file exists "${base}.nts"]} { + set type ts + set ts [ts fetch $file] + set img 741_1_10_Video_Title.png + set pad 0 + } else { + set type gen + set ts 0 + set img 743_4_10_Video_Xvid_File.png + set pad "2 2 2 2" } - source /mod/var/mongoose/lib/epg.class - puts " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Title[$ts get title]
Synopsis[$ts get synopsis]
Definition +
+ + $bfile + " - if {[$ts get definition] eq "HD"} { - puts "" - } else { - puts "" + + # Icons + + set locked 0 + if {$type eq "ts"} { + # HD / SD + if {[$ts get definition] eq "HD"} { + set img "172_1_00_HD" + } else { + set img "172_1_26_SD" + } + puts "" + + # Locked + if {[$ts flag "Locked"] > 0} { + set locked 1 + puts "" + } } - puts "
Channel[epg channelicon [$ts get channel_name] 50 "vertical-align: middle"] - [$ts get channel_num] - [$ts get channel_name]
Start Time" - puts [clock format [$ts get start] -format "%c %Z"] - puts "
End Time" - puts [clock format [$ts get end] -format "%c %Z"] - puts "
Duration[$ts duration] minute(s).
Size[$ts size] MiB
Flags[$ts get flags]
+ + # Opt+ button + + puts " + + + +
" - exit + puts "" } if {[dict exists $_cgi dir]} { @@ -173,158 +95,29 @@ if {[dict exists $_cgi dir]} { set dir "/media/My Video" } +###################################################################### +# Render web page + source /mod/var/mongoose/html/lib/header.jim -puts { +puts { + + - - + - +
+
-
-
- - +
} - }, -function (action, el, pos) -{ - var ts = $(el).parent().prevAll('a.ts').last().attr('file'); - var did = $(el).attr('did'); - switch (action) - { - case 'delete': - confirm_action('delete', delete_callback, ts, did); - break; - - case 'lock': - confirm_action('change the lock on', lock_callback, ts, did); - break; - - case 'download': - window.location.href = ts; - break; - - default: - alert('Unhandled action: ' + action); - break; - } -} - ); - } - - var $confirm = $('#confirm').dialog({ - modal: true, autoOpen: false, - height: 160, width: 500, - show: 'fade', hide: 'fade', - draggable: false, resizable: false - }); - - var confirm_action = function(action, callback, ts, id) { - var bts = ts.replace(/.*\/|\.[^.]*$/g, ''); - $confirm.dialog('option', 'buttons', { - 'Yes': function() { $(this).dialog('close'); - callback(ts, id); }, - 'No': function() {$(this).dialog('close');} - - }); - $('#confirm').empty().html( - 'Are you sure you wish to ' + action + '
' + - '' + bts + ' ?' - ); - $confirm.dialog('open'); - } - - var delete_callback = function(ts, id) { - var el = 'div.tsfile#' + id; - var results = el + ' .results'; - var url = window.location.pathname + '?tsfile=' + - encodeURIComponent(ts) + '&action=delete'; - $(results).load(url, function() { - $(el).delay(3000).slideUp(300, function() { - $(el).remove(); - }); - }); - } - - var lock_callback = function(ts, id) { - var el = 'div.tsfile#' + id; - var results = el + ' .results'; - var url = window.location.pathname + '?tsfile=' + - encodeURIComponent(ts) + '&action='; - - $(results).load(url + 'lock', function() { - $(results).delay(3000).slideUp(150, - function() { - $(el).load(url + 'entry', function() { - bindmenu(el + ' img.opt'); - });; - } - ); - }); - } - - // Dialogue init - var $dialog = $('#dialogue').dialog({ - title: "Recording Details", - modal: false, autoOpen: false, - height: 600, width: 700, - show: 'scale', hide: 'fade', - draggable: true, resizable: true, - buttons: { - "Close": function() { - $(this).dialog('close'); - } - }, - close: function(e,u) { $('#dialogue').empty().html( - 'loading'); } - }); - - $(document).ready(function() { - - $('#optmenu').disableContextMenuItems('#rename,#title'); - bindmenu('img.opt'); - - $('a.ts').click(function(e) { - e.preventDefault(); - var file = $(this).attr('file'); - var url = window.location.pathname + '?tsfile=' + - encodeURIComponent(file); - $('#dialogue').load(url); - $dialog.dialog('open'); - }); - - }); - -} - -puts {
} # Breadcrumb path puts "

" @@ -336,6 +129,7 @@ foreach part [split $dir /] { } puts "

" +# Parent directory set parent [join [lrange [split $dir /] 0 end-1] /] if {$parent ne ""} { puts " @@ -347,6 +141,7 @@ if {$parent ne ""} { " } +# Strip double slashes regsub -all -- {\/+} "$dir/*" "/" dir foreach file [lsort [glob -nocomplain "$dir"]] { diff --git a/var/mongoose/cgi-bin/browse/browse.js b/var/mongoose/cgi-bin/browse/browse.js new file mode 100755 index 0000000..d21f8a0 --- /dev/null +++ b/var/mongoose/cgi-bin/browse/browse.js @@ -0,0 +1,145 @@ + +function delete_callback(file, type, id) +{ + var el = 'div.bf#' + id; + var results = el + ' .results'; + var url = '/cgi-bin/browse/delete.jim?file=' + + encodeURIComponent(file) + '&type=' + type; + $(results).load(url, function() { + $(el).delay(3000).slideUp(300, function() { + $(el).remove(); + }); + }); +} + +function lock_callback(file, type, id) +{ + var el = 'div.bf#' + id; + var results = el + ' .results'; + var url = '/cgi-bin/browse/lock.jim?file=' + + encodeURIComponent(file); + + $(results).load(url, function() { + $(results).delay(3000).slideUp(150); + }); +} + +var $confirm; // Populated after DOM is loaded. + +function confirm_action(action, callback, file, type, id) +{ + var bfile = file.replace(/.*\/|\.[^.]*$/g, ''); + $confirm.dialog('option', 'buttons', { + 'Yes': function() { $(this).dialog('close'); + callback(file, type, id); }, + 'No': function() {$(this).dialog('close');} + + }); + $('#confirm').empty().html( + 'Are you sure you wish to ' + action + '
' + + '' + bfile + ' ?' + ); + $confirm.dialog('open'); +} + +function preparemenu(el, menu) +{ + if (el.attr('type') == 'ts') + { + if (el.attr('locked') == 1) + { + $(menu).changeContextMenuItem('#lock', 'Unlock'); + $('#optmenu').disableContextMenuItems('#delete'); + } + else + { + $(menu).changeContextMenuItem('#lock', 'Lock'); + $('#optmenu').enableContextMenuItems('#delete'); + } + } + else + { + $('#optmenu').enableContextMenuItems('#delete'); + $('#optmenu').disableContextMenuItems('#lock'); + } +} + +function menuclick(action, el, pos) +{ + var file = $(el).parent().prevAll('a.bf').last().attr('file'); + var type = $(el).attr('type'); + var id = $(el).attr('did'); + switch (action) + { + case 'delete': + confirm_action('delete', delete_callback, file, type, id); + break; + + case 'lock': + confirm_action('change the lock on', lock_callback, + file, type, id); + break; + + case 'download': + window.location.href = file; + break; + + default: + alert('Unhandled action: ' + action); + break; + } +} + +$(document).ready(function() { + + // Bind context menu to opt+ image + $('img.opt').contextMenu( + { + menu: 'optmenu', + leftButton: true, + beforeShow: preparemenu + }, + menuclick + ); + + // Disable items which are not yet implemented. + $('#optmenu').disableContextMenuItems('#rename,#title'); + + // Create reusable dialogue. + var $dialog = $('#dialogue').dialog({ + title: "Media Details", + modal: false, autoOpen: false, + height: 600, width: 700, + show: 'scale', hide: 'fade', + draggable: true, resizable: true, + buttons: { + "Close": function() { + $(this).dialog('close'); + } + }, + close: function(e,u) { $('#dialogue').empty().html( + 'loading'); } + }); + + // Bind dialogue open to filenames. + $('a.bf').click(function(e) { + e.preventDefault(); + var file = $(this).attr('file'); + var type = $(this).attr('type'); + var url = '/cgi-bin/browse/file.jim?file=' + + encodeURIComponent(file) + '&type=' + type; + $('#dialogue').load(url); + $dialog.dialog('open'); + }); + + // Create re-usable confirmation dialogue. + $confirm = $('#confirm').dialog({ + modal: true, autoOpen: false, + height: 160, width: 500, + show: 'fade', hide: 'fade', + draggable: false, resizable: false + }); +}); + + + diff --git a/var/mongoose/cgi-bin/browse/delete.jim b/var/mongoose/cgi-bin/browse/delete.jim new file mode 100755 index 0000000..bfc8ace --- /dev/null +++ b/var/mongoose/cgi-bin/browse/delete.jim @@ -0,0 +1,27 @@ +#!/mod/bin/jimsh + +package require cgi +source /mod/var/mongoose/lib/ts.class + +puts "Content-Type: text/html" +puts "" + +cgi_input +#cgi_dump + +set file [dict get $_cgi file] +set type [dict get $_cgi type] + +if {$type eq "ts"} { + set ts [ts fetch $file] + if {[$ts delete]} { + puts "Successfully deleted $file." + } else { + puts "Problem deleting $file, [$ts get error]" + } + exit +} + +file delete $file +puts "Successfully deleted $file." + diff --git a/var/mongoose/cgi-bin/browse/ffmpeg.jim b/var/mongoose/cgi-bin/browse/ffmpeg.jim new file mode 100755 index 0000000..a5ac430 --- /dev/null +++ b/var/mongoose/cgi-bin/browse/ffmpeg.jim @@ -0,0 +1,17 @@ +#!/mod/bin/jimsh + +package require cgi + +puts "Content-Type: text/html" +puts "" + +cgi_input +#cgi_dump + +if [file exists /mod/bin/ffmpeg] { + set file [dict get $_cgi file] + puts [exec /mod/var/mongoose/lib/ffmpeg -i $file] +} else { + puts "Install ffmpeg package for more information..." +} + diff --git a/var/mongoose/cgi-bin/browse/file.jim b/var/mongoose/cgi-bin/browse/file.jim new file mode 100755 index 0000000..2f7eda9 --- /dev/null +++ b/var/mongoose/cgi-bin/browse/file.jim @@ -0,0 +1,101 @@ +#!/mod/bin/jimsh + +package require cgi +source /mod/var/mongoose/lib/pretty_size + +puts "Content-Type: text/html" +puts "" + +cgi_input +#cgi_dump + +#set _cgi(file) "/media/My Video/Dangermouse/Series 1/01_rogue_robots.avi" + +if {![dict exists $_cgi file]} { exit } + +set file [dict get $_cgi file] +set type [dict get $_cgi type] + +file stat $file st +set sz [pretty_size $st(size)] + +if {$type eq "ts"} { + source /mod/var/mongoose/lib/epg.class + source /mod/var/mongoose/lib/ts.class + + set ts [ts fetch $file] + + puts " + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Title[$ts get title]
Synopsis[$ts get synopsis]
Definition + " + if {[$ts get definition] eq "HD"} { + puts "" + } else { + puts "" + } + puts "
Channel[epg channelicon [$ts get channel_name] 50 "vertical-align: middle"] + [$ts get channel_num] - [$ts get channel_name]
Start Time" + puts [clock format [$ts get start] -format "%c %Z"] + puts "
End Time" + puts [clock format [$ts get end] -format "%c %Z"] + puts "
Duration[$ts duration] minute(s).
Size$sz
Flags[$ts get flags]
+ " + exit +} + +# Otherwise, for a general file. + +puts " + + + + + + + + + + + +
File$file
Size$sz
Info + Loading... +
+" + +set url "/cgi-bin/browse/ffmpeg.jim?file=[cgi_quote_url $file]" +puts { +} + diff --git a/var/mongoose/cgi-bin/browse/lock.jim b/var/mongoose/cgi-bin/browse/lock.jim new file mode 100755 index 0000000..2ff339f --- /dev/null +++ b/var/mongoose/cgi-bin/browse/lock.jim @@ -0,0 +1,24 @@ +#!/mod/bin/jimsh + +package require cgi +source /mod/var/mongoose/lib/ts.class + +puts "Content-Type: text/html" +puts "" + +cgi_input +#cgi_dump + +set file [dict get $_cgi file] +set ts [ts fetch $file] + +set action lock +if {[$ts flag "Locked"]} { set action unlock } + +if {[$ts $action]} { + puts "Successfully [set action]ed $file." +} else { + puts "Problem [set action]ing $file, + [$ts get error]" +} + diff --git a/var/mongoose/html/css/style.css b/var/mongoose/html/css/style.css index af8bdf2..15b48b7 100644 --- a/var/mongoose/html/css/style.css +++ b/var/mongoose/html/css/style.css @@ -101,7 +101,7 @@ table.keyval td color: black; } -pre +pre, .pre { font-family: Consolas, 'Courier New', Courier, monospace; color: black; diff --git a/var/mongoose/lib/ffmpeg b/var/mongoose/lib/ffmpeg new file mode 100755 index 0000000..c39180b --- /dev/null +++ b/var/mongoose/lib/ffmpeg @@ -0,0 +1,8 @@ +#!/bin/sh + +/mod/bin/ffmpeg "$@" 2>&1 | sed ' + 1,8d + $d +' +exit 0 + diff --git a/var/mongoose/lib/pretty_size b/var/mongoose/lib/pretty_size new file mode 100644 index 0000000..6dc84f5 --- /dev/null +++ b/var/mongoose/lib/pretty_size @@ -0,0 +1,15 @@ + +if {[expr ! [exists -proc pretty_size ]]} { + proc pretty_size {size} { + set units {bytes KiB MiB GiB TiB} + + for {set i 0} {$size > 1023} {incr i} { + set size $($size / 1024.0) + } + + set size [format "%.2f" $size] + + return "$size [lindex $units $i]" + } +} + diff --git a/var/mongoose/lib/ts.class b/var/mongoose/lib/ts.class index f4be414..a208703 100644 --- a/var/mongoose/lib/ts.class +++ b/var/mongoose/lib/ts.class @@ -20,12 +20,8 @@ ts method duration {} { } ts method size {} { - set sz "??" - catch { - file stat $file st - set sz [expr $st(size) / 1048576] - } - return $sz + file stat $file st + return $st(size) } ts method _parse {line} {