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 "
}
- },
-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(
- '

'); }
- });
-
- $(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(
+ '

'); }
+ });
+
+ // 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} {