Browse Source

first commit

master
sanj 14 years ago
commit
510feb01d3
  1. 4
      chrome.manifest
  2. 307
      chrome/content/classes.js
  3. 556
      chrome/content/jquery-ui.js
  4. 3549
      chrome/content/jquery.js
  5. 21
      chrome/content/menu.js
  6. 15
      chrome/content/menu.xul
  7. 116
      chrome/content/player.js
  8. 184
      chrome/content/staticfuncs.js
  9. 126
      chrome/content/styles.css
  10. 216
      chrome/content/transcribe.html
  11. 29
      install.rdf

4
chrome.manifest

@ -0,0 +1,4 @@
content speedtrans chrome/content/
overlay chrome://browser/content/browser.xul chrome://speedtrans/content/menu.xul

307
chrome/content/classes.js

@ -0,0 +1,307 @@
//elem = string (elementId to make TextArea)
var TextArea = function(elem) {
this.elem = $('#' + elem);
this.hasFocus = false;
this.width = this.elem.width();
this.init()
}
TextArea.prototype.init = function() {
var that = this;
var e = this.elem;
var tc;
e.focus(function() {
that.hasFocus = true;
}).blur(function() {
that.hasFocus = false;
});
e.dblclick(function() {
if (tc = that.isTc()) {
Video.set(tc);
} else {
that.insertTc();
}
Video.togglePause();
});
}
//returns tc in ms if cursor is at a time-code, else returns false
TextArea.prototype.isTc = function() {
var that = this;
var e = this.elem;
var eDom = e.get(0);
var val = e.val();
var pos = eDom.selectionStart;
var word = this.getWord(pos);
if (isValidTimecode(word)) {
return npt2ms(word);
} else {
return false;
}
}
//inserts current timecode at cursor position
TextArea.prototype.insertTc = function() {
var that = this;
var e = that.elem;
var eDom = e.get(0);
var scrollTop = eDom.scrollTop;
var val = this.elem.val();
var pos = eDom.selectionStart;
var tcNpt = ms2npt(Video.get());
var newVal = val.substring(0,pos) + "\n" + tcNpt + "\n" + val.substring(pos, val.length);
e.val(newVal);
e.focus();
eDom.selectionStart = pos + tcNpt.length + 1;
eDom.selectionEnd = pos + tcNpt.length + 1;
eDom.scrollTop = scrollTop + 15;
}
//gets the word at character pos (int) [in val (str)]
TextArea.prototype.getWord = function(pos, val) {
if (!val) {
val = this.elem.val();
}
var c;
var i = pos;
var j = pos;
while (c != " " && c != "\n") {
if (i==0) {
i = -1;
break;
}
i--;
c = val.substring(i,i+1);
}
var firstLetter = i+1;
var d;
while (d != " " && d != "\n") {
if (j >= val.length) {
break;
}
j++;
d = val.substring(j,j+1);
}
var lastLetter = j;
var word = val.substring(firstLetter, lastLetter);
return word;
}
//takes an srt as param, loads into txtarea
TextArea.prototype.fromSrt = function(srt) {
var spans = [];
srt = srt.replace('\r\n|\r|\n', '\n')
srt = strip(srt);
var srt_ = srt.split('\n\n');
for(s in srt_) {
st = srt_[s].split('\n');
if(st.length >=2) {
var n = st[0];
var i = strip(st[1].split(' --> ')[0]);
var o = strip(st[1].split(' --> ')[1]);
var t = st[2];
if(st.length > 2) {
for(j=3; j<st.length;j++) {
t += '\n'+st[j];
}
}
var is = toSeconds(i);
var os = toSeconds(o);
spans[spans.length] = new Span(is, os, t, spans.length);
}
}
var out = '';
for (span in spans) {
if (spans.hasOwnProperty(span)) {
var sp = spans[span];
out += ms2npt(sp.tcInMs) + "\n";
out += sp.text;
out += "\n";
//If the outpoint of current span is equal to inpoint of next span, dont print out timecode, and just add the extra \n to go to next span.
if (span < spans.length - 1) {
var p = parseInt(span) + 1;
if (spans[p].tcInMs != sp.tcOutMs) {
out += ms2npt(sp.tcOutMs) + "\n\n";
} else {
out += "\n";
}
}
}
}
this.elem.val(out);
}
function strip(s) {
return s.replace(/^\s+|\s+$/g,"");
}
function toSeconds(t) {
var s = 0.0;
if(t) {
var p = t.split(':');
for(i=0;i<p.length;i++) {
s = s * 60 + parseFloat(p[i].replace(',', '.'))
}
}
return s;
}
function spansToSrt(arr, fmt, start_no) {
if (typeof start_no == 'undefined') {
start_no = 1;
}
var srt = '';
var srtNo = start_no;
for (var k=0; k < arr.length; k++) {
var s = arr[k];
if (s.text.trim() == '') {
} else {
var text = s.text.trim();
linebreaksRegex = new RegExp('\n+', "g")
text = text.replace(linebreaksRegex, "\n");
if (!s.tcOutMs) {
s.tcOutMs = parseInt(Video.player.duration * 1000);
}
if (fmt == 'srt') {
srt += srtNo + " ";
srt += "\n";
srt += "0" + ms2npt(s.tcInMs).replace(".", ",") + " --> " + "0" + ms2npt(s.tcOutMs).replace(".", ",");
srt += "\n";
srt += text;
srt += "\n\n";
}
else if (fmt == 'enc') {
srt += srtNo + ms2frames(s.tcInMs) + " " + ms2frames(s.tcOutMs) + " " + text;
srt += "\n\n";
}
srtNo++;
}
}
return srt;
}
//returns textarea formatted to .srt
TextArea.prototype.toSrt = function(fmt) {
if (!fmt) var fmt = 'srt';
var text = this.elem.val();
var lines = [];
lines = text.split("\n");
var i=0;
var j=0;
spans = [];
while (i < lines.length) {
var l = lines[i];
if (isValidTimecode(l.trim())) {
var tcIn = l.trim();
var t = "";
var thisLine = '';
while (!isValidTimecode(thisLine.trim())) {
i++;
if (i >= lines.length) {
break;
}
thisLine = lines[i];
if (!isValidTimecode(thisLine.trim())) {
t += thisLine + "\n";
}
}
spans[j] = new Span(tcIn, thisLine, t, j);
j++;
} else {
i++;
}
}
var srt = spansToSrt(spans, fmt);
// console.log(srt);
return srt;
}
//Using spans as GLOBAL is ridiculous - please fix.
TextArea.prototype.addTime = function(ms, start_no) {
// console.log(ms);
if (typeof spans == 'undefined') {
this.toSrt();
}
var s = [];
for (var i=0; i<spans.length;i++) {
s[i] = {
index: i,
tcOutMs: spans[i].tcOutMs + ms,
text: spans[i].text,
tcInMs: spans[i].tcInMs + ms
}
}
return spansToSrt(s, 'srt', start_no)
}
//creates new Span (tcIn and tcOut in npt format)
var Span = function(tcIn, tcOut, text, index) {
this.index = index;
this.tcOutMs = npt2ms(tcOut);
this.text = text;
this.tcInMs = npt2ms(tcIn);
}
var SeekBar = function(elem) {
this.elem = $('#' + elem);
this.pointerId = "seekPointer";
this.width = this.elem.width();
this.init()
}
SeekBar.prototype.init = function() {
var that = this;
var e = $('<div />');
e.attr("id", that.pointerId);
e.draggable({
containment: 'parent',
axis: 'horizontally',
drag: function() {
clearInterval(videoListener);
var pos = that.get();
$('#timeCode').html(ms2npt(pos));
},
stop: function() {
var pos = that.get();
Video.set(pos);
videoListener = setInterval(Video.listener, 250);
}
});
that.elem.append(e);
this.pointerElem = e;
}
//gets current time-code (int) of seekbar position
SeekBar.prototype.get = function() {
var cssPos = parseInt(this.pointerElem.css("left"));
var pos = parseInt((cssPos / this.width) * (Video.player.duration * 1000));
return pos;
}
//sets seek bar css pos according to current time-code
SeekBar.prototype.set = function(ms) {
var cssPos = parseInt(((ms / 1000) / Video.player.duration) * this.width);
this.elem.css("left", cssPos + "px");
}
/*
var KeyboardController = function() {
this.
}
*/
function loadSrt(filename) {
// alert("hmm.. you have a .srt file but not a txt file - this is a bug. sorry.");
var txt = mozillaLoadFile(filename);
textArea.fromSrt(txt);
}
function loadMeta(filename) {
var m = mozillaLoadFile(filename);
}
function loadSrtTxt(filename) {
var txt = mozillaLoadFile(filename);
$('#txt').val(txt);
}

556
chrome/content/jquery-ui.js

File diff suppressed because one or more lines are too long

3549
chrome/content/jquery.js

File diff suppressed because it is too large

21
chrome/content/menu.js

@ -0,0 +1,21 @@
var padma={
openAnnot:function()
{
window.open("chrome://speedtrans/content/transcribe.html");
/*
window.open("chrome://speedtrans/content/transcribe.html",
"annot", "chrome,centerscreen,resizable=yes,toolbar=no,menubar=no");
*/
}
}
function getMainWindow() {
return window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
}

15
chrome/content/menu.xul

@ -0,0 +1,15 @@
<?xml version="1.0"?>
<overlay id="annot"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/x-javascript"
src="chrome://speedtrans/content/menu.js" />
<menupopup id="menu_ToolsPopup">
<menuitem id="annot_menu" image="chrome://speedtrans/content/icon.png"
class="menuitem-iconic"
insertafter="javascriptConsole,devToolsSeparator"
label="Pad.ma Transcription Client"
oncommand="padma.openAnnot();"/>
</menupopup>
</overlay>

116
chrome/content/player.js

@ -0,0 +1,116 @@
function Player() {
this.supportsOverlay = false;
this.muted = false;
}
Player.prototype.init = function(elemID) {
//make overlay settings happy..., add a dummy element
this.player = document.getElementById(elemID);
}
Player.prototype.play = function() { }
Player.prototype.pause = function() { }
Player.prototype.get = function() { }
Player.prototype.listener = function() { }
Player.prototype.set = function(pos) { }
Player.prototype.mute = function(pos) { }
Player.prototype.seekFwd = function(ms) {
var currentMs = this.get();
var newMs = currentMs + ms;
this.set(newMs);
}
Player.prototype.seekBack = function(ms) {
var currentMs = this.get();
var newMs = currentMs - ms;
this.set(newMs);
}
Player.prototype.unmute = function(pos) { }
/* Player.prototype.url = function(pos) {
var timecode = pos2npt(pos);
var link = video.url;
if(pos > 0)
link += "?t=npt:" + timecode;
return link;
};
*/
function VideoPlayer() {
this.supportsOverlay = true;
this.isPlaying = false;
}
VideoPlayer.prototype = new Player();
VideoPlayer.prototype.init = function(elemID) {
this.player = document.getElementById(elemID);
this.width = $(this.player).attr('width');
this.height = $(this.player).attr('height');
}
VideoPlayer.prototype.set = function(pos) {
/* var url = this.url(pos);
var autoplay = 'true';
if(this.isPlaying)
varautoplay = 'true';
if(this.player) {
var element = $(this.player);
this.player.pause();
} else {
var element = $('#' + playerID);
}
this.player = document.createElement('video');
this.player.id = playerID;
this.player.width = this.width;
this.player.height = this.height;
this.player.setAttribute('src', url);
//this.player.setAttribute('autoplay', autoplay);
element.replaceWith(this.player); */
this.player.currentTime = pos / 1000;
}
VideoPlayer.prototype.get = function() {
try {
return parseInt(this.player.currentTime * 1000);
} catch(err) { }
return -1;
}
VideoPlayer.prototype.play = function() {
this.isPlaying = true;
this.player.play();
}
VideoPlayer.prototype.pause = function() {
this.isPlaying = false;
this.player.pause();
}
VideoPlayer.prototype.mute = function(pos) {
this.player.muted = true;
this.muted = true;
}
VideoPlayer.prototype.unmute = function(pos) {
this.player.muted = false;
this.muted = false;
}
VideoPlayer.prototype.togglePause = function() {
if (Video.isPlaying == true) {
Video.pause();
} else {
Video.play();
}
}
VideoPlayer.prototype.listener = function() {
var ms = Video.get();
var npt = ms2npt(ms);
$('#timeCode').html(npt);
var seekBarPos = parseInt((ms / (Video.duration * 1000)) * 320);
$('#seekPointer').css("left", seekBarPos + "px");
}
VideoPlayer.prototype.setDuration = function(duration) {
this.duration = duration;
}

184
chrome/content/staticfuncs.js

@ -0,0 +1,184 @@
function npt2ms(npt) {
var ms = 0.0
npt = String(npt);
var p = npt.split(':')
for(i=0;i<p.length;i++)
ms = ms * 60 + parseFloat(p[i])
return ms * 1000;
}
function ms2npt(ms) {
var it, ss, mm, hh, npt;
var it = parseInt(ms / 1000)
ms = ms - it * 1000;
if (ms.toString().length > 3) {
ms = ms.toString().substring(0,3);
}
ss = it % 60;
mm = ((it - ss) / 60) % 60;
hh = ((it - (mm * 60) - ss) / 3600) % 60;
npt = hh+':'+strpad(mm.toString(), '0', 2, 'left')
npt += ':'+strpad(ss.toString(), '0', 2, 'left')
npt += '.'+strpad(ms.toString(), '0', 3, 'left')
return npt;
}
function ms2frames(ms, fmt) {
if (!fmt) var fmt = "PAL";
var npt = ms2npt(ms);
var dotpos = npt.lastIndexOf(".");
var mmStr = npt.substring(dotpos + 1, npt.length);
var mmInt = parseInt(mmStr);
if (fmt == 'PAL') {
var frames = parseInt((mmInt / 1000) * 24);
} else if (fmt == "NTSC") {
var frames = parseInt((mmInt / 1000) * 29.97);
}
var framesTc = '';
var joinToken = ":";
var framesTc = npt.substring(0, dotpos ) + joinToken + frames;
return framesTc;
}
function ms2time(ms) {
var npt = ms2npt(ms)
return npt.substr(npt.length-9, npt.length-6);
}
function framesToNpt(timeCode) {
var frames = timeCode.substring(9, 11);
var ms = parseInt(frames) / 25 * 1000;
var ms = String(ms);
var ms = strpad(ms, '0', 3, 'right');
var timeCodeNpt = timeCode.substring(0,8) + "." + ms;
return timeCodeNpt;
}
function strpad(str, pad, len, dir) {
while (str.length < len) {
if (dir == 'left')
str = pad + str;
else if (dir == 'right')
str = str + pad;
}
return str;
}
function isValidTimecode(tc) {
var tc = $.trim(tc);
var nptRegex = new RegExp("^[0-9][0-9]?\:[0-9][0-9]\:[0-9][0-9][\.|\,|\:][0-9]?[0-9]?[0-9]?$");
return nptRegex.test(tc);
}
function selectFile() {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
const nsIFilePicker = Components.interfaces.nsIFilePicker;
var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(window, "Choose a File", nsIFilePicker.modeOpen);
fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText);
fp.appendFilters("Video Files", "*.ogg;*.ogv;*.ogx;*.dv;*.avi;*.mov");
var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
var file = fp.file;
var path = fp.file.path;
return path;
}
return false;
}
function mozillaSaveFile(filePath,content)
{
if(window.Components) {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);
if(!file.exists())
file.create(0,0664);
var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
var out = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
out.init(file,0x20|0x02,00004,null);
os.init(out, "UTF-8", 0, 0x0000);
os.writeString(content);
//out.write(content,content.length);
os.close();
//out.flush();
out.close();
return true;
} catch(ex) {
alert(ex);
return false;
}
}
return null;
}
// Returns null if it can't do it, false if there's an error, or a string of the content if successful
function mozillaLoadFile(filePath)
{
if(window.Components) {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);
if(!file.exists())
return null;
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance(Components.interfaces.nsIFileInputStream);
inputStream.init(file,0x01,00004,null);
//var sInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance(Components.interfaces.nsIScriptableInputStream);
//sInputStream.init(inputStream);
var charset = "UTF-8";
const replacementChar = Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER;
var cInputStream = Components.classes["@mozilla.org/intl/converter-input-stream;1"]
.createInstance(Components.interfaces.nsIConverterInputStream);
cInputStream.init(inputStream, charset, 1024, replacementChar);
var str = {};
var contents = '';
while (cInputStream.readString(4096, str) != 0) {
contents += str.value;
}
//var contents = sInputStream.read(sInputStream.available());
cInputStream.close();
//sInputStream.close();
inputStream.close();
return contents;
} catch(ex) {
alert(ex);
return false;
}
}
return null;
}
function checkFileExists(filePath) {
if(window.Components) {
try {
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);
if (file.exists()) {
return true;
} else {
return false;
}
} catch(ex) {
//alert("Error");
return null;
}
}
}
function getFileNameSansExt(filename) {
var dotPos = filename.lastIndexOf(".");
if (dotPos != '-1') {
var filenameSansExt = filename.substring(0,dotPos);
} else {
var filenameSansExt = filename;
}
return filenameSansExt;
}

126
chrome/content/styles.css

@ -0,0 +1,126 @@
body {
background: #000;
color: #fff;
}
#additionalFeatures {
display: none;
}
#wrapper {
width: 100%;
height: 100%;
}
#videoWrapper {
float: left;
width: 400px;
height: 100%;
}
#selectFileDiv {
text-align: center;
}
#helpWrapper {
-moz-border-radius: 8px;
font-size: 13px;
color: #000;
border: 2px solid #999;
background: #ccc;
padding: 4px;
margin-top: 8px;
}
#video {
height: 300px;
width: 400px;
}
#txtWrapper {
width: 50%;
margin-left: 20px;
float: left;
}
#buttonsWrapper {
text-align: center;
}
#eventMetadata {
display: none;
margin-left: 20px;
float: left;
width: 50%;
}
input.eventMeta, textarea.eventMeta {
padding: 5px;
margin: 3px;
width: 250px;
}
#seekTime {
width: 20px;
}
#dateYear {
width: 30px;
}
#dateMonth {
width: 25px;
}
#dateDay {
width: 25px;
}
#description {
width: 80%;
height: 100px;
}
.button {
padding: 8px;
margin-left: 10px;
cursor: pointer;
font-size: 15px;
background: #ccc;
-moz-border-radius: 5px;
border: 2px solid #000;
color: #f33;
font-weight: bold;
}
#txt {
height: 500px;
width: 100%;
}
#seekBar {
height: 16px;
width: 320px;
margin-left: 40px;
background: #666;
opacity: 0.7;
z-index: 100;
}
#seekPointer {
height: 12px;
width: 10px;
position: relative;
margin-top: 2px;
margin-bottom: 2px;
-moz-border-radius: 10px;
background: #f00;
}
#timeCode {
color: #f00;
font-size: 12px;
font-weight: bold;
text-align: center;
}

216
chrome/content/transcribe.html

@ -0,0 +1,216 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
Pad.ma: Subtitle n more...
</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="player.js"></script>
<script type="text/javascript" src="jquery-ui.js"></script>
<script type="text/javascript" src="staticfuncs.js"></script>
<script type="text/javascript" src="classes.js"></script>
<link rel="stylesheet" href="styles.css" />
<script type="text/javascript">
//init globals
var seekBar;
var textArea;
var Video;
var filePath = false;
var spans;
var videoListener;
$(document).ready(function() {
textArea = new TextArea("txt");
$('#saveFile').click(saveFile);
$('#saveSrt').click(saveSrt);
$('#addTime').click(function() {
var timeToAdd = npt2ms($.trim($('#timeToAdd').val()));
var startNo = parseInt($('#startNo').val());
var r = textArea.addTime(timeToAdd, startNo);
$('#addTimeResult').val(r);
});
$('#showMore').toggle(function() {
$(this).text("Show Less Features");
$('#additionalFeatures').show("fast");
}, function() {
$(this).text("Show More Features");
$('#additionalFeatures').hide("fast");
});
$('#saveEncore').click(saveEncore);
$('#selectFile').click(function() {
var videoFile = selectFile();
alert(videoFile);
filePath = getFileNameSansExt(videoFile);
var srtTxtFilename = filePath + ".srt.txt";
var srtFilename = filePath + ".srt";
var metaFilename = filePath + ".txt";
if (checkFileExists(srtTxtFilename)) {
loadSrtTxt(srtTxtFilename);
} else if (checkFileExists(srtFilename)) {
loadSrt(srtFilename);
}
if (checkFileExists(metaFilename)) {
loadMeta(metaFilename);
}
$('#video').attr("src", "file://" + videoFile);
document.getElementById("video").load();
$('#video').one("loadedmetadata", function() {
$('#selectFileDiv').fadeOut();
Video = new VideoPlayer();
Video.init("video");
//
// seekBar = new SeekBar("seekBar");
Video.setDuration(Video.player.duration);
$('#insertTc').click(textArea.insertTc);
/* $('#video').click(function() {
Video.togglePause();
});
*/
$('#video').dblclick(function() {
textArea.insertTc();
});
videoListener = setInterval(Video.listener, 250);
});
});
$(document).keyup(function(e) {
//Esc
if (e.keyCode == 27 && textArea.hasFocus) {
Video.togglePause();
}
//Ins
if (e.keyCode == 45) {
if (!textArea.isTc()) {
textArea.insertTc();
}
}
//Ctrl - Seek Back
if (e.keyCode == 17) {
var seekTime = parseInt(parseFloat($('#seekTime').val()) * 1000);
var currTime = Video.get();
var newTime = currTime - seekTime;
Video.set(newTime);
}
//Alt - Seek Fwd.
if (e.keyCode == 18) {
var seekTime = parseInt(parseFloat($('#seekTime').val()) * 1000);
var currTime = Video.get();
var newTime = currTime + seekTime;
Video.set(newTime);
}
//Space - togglePause if no focus on TA
if (e.keyCode == 32 && textArea.hasFocus == false) {
Video.togglePause();
}
});
$('#fillMeta').click(function() {
$('#txtWrapper').hide();
$('#eventMetadata').show();
});
$('#doneMetadata').click(function() {
$('#eventMetadata').hide();
$('#txtWrapper').show();
});
$('.eventMeta').each(function() {
var defVal = $(this).attr('data-default');
$(this).val(defVal);
$(this).focus(function() {
if ($(this).val() == $(this).attr("data-default")) {
$(this).val('');
}
}).blur(function() {
if ($(this).val() == '') {
$(this).val($(this).attr('data-default'));
}
});
});
});
function saveFile() {
var savePath = filePath + ".srt.txt";
var content = $('#txt').val();
if (mozillaSaveFile(savePath, content)) {
alert("saved file at " + savePath);
} else {
alert("error saving file");
}
}
function saveSrt() {
var srtPath = filePath + ".srt";
var content = textArea.toSrt();
if (mozillaSaveFile(srtPath, content)) {
alert("export .srt file to " + srtPath);
} else {
alert("error exporting srt");
}
}
function saveEncore() {
var encPath = filePath + ".enc.txt";
var content = textArea.toSrt("enc");
if (mozillaSaveFile(encPath, content)) {
alert("saved encore compatible subtitle file at " + encPath);
} else {
alert("error creating encore compatible subtitle file");
}
}
</script>
</head>
<body>
<div id="wrapper">
<div id="videoWrapper">
<div id="selectFileDiv">
<button id="selectFile">Select File</button>
</div>
<video id="video" src="" controls="true">
Sorry you need <a href="http://www.mozilla.com/en-US/firefox/all-beta.html">Firefox 3.5 Beta</a> for this to work.
</video>
<div id="seekBar">
</div>
<div id="timeCode">0:00:00.000</div>
<div id="helpWrapper">
Shortcuts: <br /><br />
Esc: Pause / Unpause <br />
Insert: Insert time-code<br />
Double-click in Textarea: insert time-code <br />
Double-click on video: insert time-code<br />
Double-click on time-code in textarea: Seek video to time-code. <br />
Ctrl / Alt: Seek back / forward <input id="seekTime" value="1" /> seconds.
</div>
</div>
<div id="txtWrapper">
<textarea id="txt"></textarea><br /> <br />
<div id="buttonsWrapper">
<!-- <button id="fillMeta" class="button">Enter Metadata</button> -->
<button id="saveFile" class="button">Save File</button>
<button id="saveSrt" class="button">Export SRT</button>
<button id="saveEncore" class="button">Export to Encore</button>
<button id="showMore" class="button">Show More Features</button>
</div>
<div id="additionalFeatures">
<div id="addTimeWrap">
Time to add: <input id="timeToAdd" /><br />
Start no: <input id="startNo" /> <button id="addTime">Add</button><br />
<textarea id="addTimeResult"></textarea>
</div>
</div>
</div>
<div id="eventMetadata">
<input id="title" data-default="Title" class="eventMeta" /><br />
<input id="director" data-default="Director" class="eventMeta" /><br />
<input id="collection" data-default="Collection" class="eventMeta" /><br />
<input id="source" data-default="Source" class="eventMeta" /><br />
<textarea id="description" data-default="Event Description" class="eventMeta"></textarea><br />
Date: <input id="dateYear" data-default="YYYY" class="eventMeta" /> <input id="dateMonth" data-default="MM" class="eventMeta" /> <input id="dateDay" data-default="DD" class="eventMeta" /><br />
Logged by: <input id="loggedBy" data-default="Your name" class="eventMeta" /><br /><br />
<button id="doneMetadata" class="button">Done Adding Metadata</button>
</div>
</div>
</div>
</body>
</html>

29
install.rdf

@ -0,0 +1,29 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>b@pad.ma</em:id>
<em:version>0.2</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>1.5</em:minVersion>
<em:maxVersion>3.9</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>pad.ma transcription client</em:name>
<em:description>pad.ma offline transcription client</em:description>
<em:creator>pad.ma</em:creator>
<em:updateURL>http://files.pad.ma/annot/update.rdf</em:updateURL>
<em:updateKey>MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcI+EIEmZ2UMEMzksirJQ6rbRZebeQzM9LCf9i7EZny5umQOF+92G+DxlKrk1BC+B1ZhXHMZNBRWEhn9kuW8mgXL1JBKVPbg4RjbJ39XigtXL5wNWU6EVdUvzFH1D49HwGpDRWJhnlUTMFhJL2FW47Qg1yCttQSEYmmSum3Y77rwIDAQAB</em:updateKey>
<em:homepageURL>http://wiki.pad.ma/wiki/Annot</em:homepageURL>
<em:iconURL>chrome://annot/content/icon.png</em:iconURL>
</Description>
</RDF>
Loading…
Cancel
Save