diff --git a/CONTROL/control b/CONTROL/control
index 02627e9..8da07f8 100644
--- a/CONTROL/control
+++ b/CONTROL/control
@@ -1,7 +1,7 @@
 Package: webif
 Priority: optional
 Section: web
-Version: 0.7.3
+Version: 0.7.3-1
 Architecture: mipsel
 Maintainer: af123@hummypkg.org.uk
 Depends: mongoose(>=3.0-2),jim(>=0.71-1),jim-sqlite3(>=0.71-1),jim-cgi(>=0.4),jim-oo,jim-pack,service-control,busybox(>=1.18.3-1),lsof,epg(>=1.0.5),hmt(>=1.0.6),ssmtp
diff --git a/var/mongoose/cgi-bin/browse.jim b/var/mongoose/cgi-bin/browse.jim
index 95b9d05..ecb26eb 100755
--- a/var/mongoose/cgi-bin/browse.jim
+++ b/var/mongoose/cgi-bin/browse.jim
@@ -189,6 +189,32 @@ puts {
 		</form>
 	</div>
 
+	<div id=savestreamform title="Save streamed content"
+	    style="display: none">
+		<div class=pre id=savestream_detail></div>
+		<form id=savestream_form>
+}
+puts "<input type=hidden name=dir value=\"$dir\">"
+puts {
+		<table border=0>
+		<tr>
+		<th>
+			<label for="savestream_name">
+				<b>Filename</b>
+			</label>
+		</th>
+		<td>
+			<input type=text name="savestream_name"
+			    id="savestream_name"
+			    value="" size=70 maxlength=255
+			    class="text ui-widget-content ui-corner-all">
+			<img id=savestream_spin src=/img/loading.gif>
+		</td>
+		</tr>
+		</table>
+		</form>
+	</div>
+
 	<div id=dialogue></div>
 	<div id=confirm title="Confirmation Required"></div>
 
@@ -232,5 +258,21 @@ foreach file [lsort [glob -nocomplain "$dir"]] {
 
 puts "</fieldset>"
 
+# De-duplicate
+
+puts {
+	<small><button id=dedup>De-duplicate/tidy this folder</button></small>
+}
+
+# Streamer file
+
+if {[file exists /mnt/hd3/Streamer_down_file]} {
+	puts {
+<small><button id=save_stream file=/mnt/hd3/Streamer_down_file>
+	Save last streamed content (e.g. iPlayer/YouTube)
+</button></small>
+}
+}
+
 footer
 
diff --git a/var/mongoose/cgi-bin/browse/browse.js b/var/mongoose/cgi-bin/browse/browse.js
index 6ee4995..9960718 100755
--- a/var/mongoose/cgi-bin/browse/browse.js
+++ b/var/mongoose/cgi-bin/browse/browse.js
@@ -88,6 +88,18 @@ function rename_submit()
 	    function() { window.location.reload(true); });
 }
 
+function savestream_submit()
+{
+	var s = $('#savestream_form').serialize();
+	var sf = $('#save_stream').attr('file');
+	$('#savestream_spin').show();
+	$.get('/cgi-bin/browse/savestream.jim?sfile=' +
+	    encodeURIComponent(sf) + '&' + s,
+	    function() {
+		window.location.reload(true);
+	    });
+}
+
 var $confirm;	// Populated after DOM is loaded.
 
 function confirm_action(action, callback, file, type, id)
@@ -266,6 +278,19 @@ var menuclick = function(action, el, pos)
 		close: function() { $('#rename').val(''); }
 	});
 
+	$('#savestreamform').dialog({
+		autoOpen: false,
+		height: 'auto', width: 'auto',
+		modal: true,
+		buttons: {
+			"Save": savestream_submit,
+			"Cancel": function() {
+				$(this).dialog('close');
+			}
+		},
+		close: function() { $('#savestream_name').val(''); }
+	});
+
 	// Create re-usable confirmation dialogue.
 	$confirm = $('#confirm').dialog({
 		modal: true, autoOpen: false,
@@ -283,5 +308,18 @@ var menuclick = function(action, el, pos)
 	// Flag folders with unwatched items
 	$.getJSON('/cgi-bin/browse/newdir.jim?dir=' + encodeURIComponent(dir),
 		new_folder_callback);
+
+	$('#dedup').button().click(function() {
+		window.location = '/cgi-bin/dedup.jim?dir='
+		    + encodeURIComponent(dir);
+	});
+
+	$('#save_stream').button().click(function() {
+		$('#savestream_spin').hide();
+		$('#savestreamform').dialog('open');
+		$('#savestream_detail').load(
+		    '/cgi-bin/browse/ffmpeg.jim?file=' +
+		    encodeURIComponent($('#save_stream').attr('file')));
+	});
 });
 
diff --git a/var/mongoose/cgi-bin/browse/savestream.jim b/var/mongoose/cgi-bin/browse/savestream.jim
new file mode 100755
index 0000000..464b682
--- /dev/null
+++ b/var/mongoose/cgi-bin/browse/savestream.jim
@@ -0,0 +1,21 @@
+#!/mod/bin/jimsh
+
+package require cgi
+source /mod/var/mongoose/lib/ts.class
+
+puts "Content-Type: text/html"
+puts ""
+
+cgi_input
+#cgi_dump
+
+set dir [cgi_get dir "/media/My Video"]
+set file [file tail [cgi_get savestream_name]]
+set sfile [cgi_get savestream_source "/mnt/hd3/Streamer_down_file"]
+if {$file == "0"} { exit }
+if {[string length [string trim $file]] == 0} { exit }
+
+if {[file extension $file] ne ".mp4"} { append file ".mp4" }
+
+file copy $sfile "$dir/$file"
+
diff --git a/var/mongoose/cgi-bin/dedup.jim b/var/mongoose/cgi-bin/dedup.jim
new file mode 100755
index 0000000..8a662d8
--- /dev/null
+++ b/var/mongoose/cgi-bin/dedup.jim
@@ -0,0 +1,102 @@
+#!/mod/bin/jimsh
+
+package require cgi
+source /mod/var/mongoose/lib/setup
+require ts.class pretty_size altrow
+
+puts "Content-Type: text/html"
+puts ""
+
+cgi_input
+#cgi_dump
+
+set dir [cgi_get dir "/media/My Video"]
+set doit [cgi_get doit 0]
+
+# Strip double slashes
+
+header
+
+puts "<fieldset style=\"display: inline\">
+<legend>De-duplicate <span id=dir>$dir</span></legend>
+<table class=borders>
+<tr>
+	<th>File</th>
+	<th>Proposed Filename</th>
+	<th>Proposed Title</th>
+	<th>Status</th>
+</tr>
+"
+
+regsub -all -- {\/+} "$dir/*" "/" dir
+
+foreach file [lsort [glob -nocomplain "$dir"]] {
+	if {[file extension $file] ne ".hmt"} { continue }
+	altrow
+	set ts [ts fetch $file 1]
+	set base [file tail [file rootname $file]]
+	puts "<td nowrap>$base</td>"
+	set syn [$ts get synopsis]
+	regsub -nocase -all -- {^new series\.* *} $syn "" syn
+	regsub -all -- { *[:].*$} $syn "" syn
+	if {[string length $syn] > 40} {
+		regsub -all -- { *[\.].*$} $syn "" syn
+	}
+	if {[string length $syn] < 6} {
+		append syn " [$ts get title]"
+	}
+	regsub -all -- {[\/ &]} $syn "_" fn
+	puts "<td>$fn</td>"
+	puts "<td>$syn</td>"
+	puts "<td>"
+	if {[file exists "$dir/$fn.hmt"]} {
+		puts "Duplicate"
+	} elseif {[string length $syn] > 40} {
+		puts "Cannot process"
+	} elseif {$base eq $fn} {
+		puts "Already done"
+	} elseif {$doit} {
+		# Dooooo, it.
+		$ts settitle $syn
+		$ts renamegroup $file $fn
+		puts "Done"
+	}
+	
+	puts "</td>"
+	puts "</tr>"
+}
+
+puts {
+</table>
+</fieldset>
+<div style="padding-top: 2em">
+<small>
+<button id=browse>Back to media browser</button>
+}
+
+if {!$doit} { puts "<button id=dedup>Process folder</button>" }
+
+puts {
+</small>
+
+</div>
+
+<script type=text/javascript>
+$('#browse').button().click(function() {
+	window.location = '/cgi-bin/browse.jim?dir=' +
+	    encodeURIComponent($('#dir').text());
+});
+}
+
+if {!$doit} {
+	puts {
+	$('#dedup').button().click(function() {
+		window.location = window.location + '&doit=1';
+	});
+	}
+}
+
+puts "</script>"
+
+footer
+
diff --git a/var/mongoose/cgi-bin/xepg.jim b/var/mongoose/cgi-bin/xepg.jim
index 1b668e8..b4b5f23 100755
--- a/var/mongoose/cgi-bin/xepg.jim
+++ b/var/mongoose/cgi-bin/xepg.jim
@@ -41,8 +41,9 @@ set ett $(int($stt + $seconds))
 set offset $(($ostt - $stt) / 1800.0)
 
 set chanpx 120
-set eventpx 780
+set eventpx 1000
 set totalpx $($chanpx + $eventpx)
+set contwidth $($totalpx + 50)
 
 set hourpx $($eventpx / $hours)
 set minpx $($hourpx / 60.0)
@@ -65,7 +66,8 @@ puts "<button id=later>Later &gt;&gt;&gt;</button>"
 puts "</div>"
 
 puts "
-<div id=xepg> <div id=xepgnow></div>
+<div id=xepg style=\"min-width: ${contwidth}px; overflow: auto\">
+<div id=xepgnow></div>
 <div id=xegrid>
 "
 
@@ -96,7 +98,8 @@ foreach e $records {
 
 		puts "[$e channel_icon 30]&nbsp;"
 		puts "$chnum
-	    <a href=/cgi-bin/epg_service.jim?service=[$e get service_id]>
+	    <a href=/cgi-bin/epg_service.jim?service=[$e get service_id]
+		title=\"[$e get channel_name]\">
 	    [$e get channel_name]
 	    </a></div>"