Commit 8177e5eb authored by Andrey Filippov's avatar Andrey Filippov

Merge branch 'master' of github.com:Elphel/elphel-apps-camogm

parents 49435a6f 569ab463
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<projectDescription> <projectDescription>
<name>camogm</name> <name>elphel-apps-camogm</name>
<comment></comment> <comment></comment>
<projects> <projects>
</projects> </projects>
......
GUIDIR = camogmgui
PROGS = camogm PROGS = camogm
PHPSCRIPTS = camogmstate.php PHPSCRIPTS = camogmstate.php $(GUIDIR)/camogmgui.php $(GUIDIR)/camogmgui.css $(GUIDIR)/camogmgui.js $(GUIDIR)/camogm_interface.php \
$(GUIDIR)/SpryTabbedPanels.css $(GUIDIR)/SpryTabbedPanels.js $(GUIDIR)/xml_simple.php $(GUIDIR)/SpryCollapsiblePanel.css \
$(GUIDIR)/SpryCollapsiblePanel.js
CONFIGS = qt_source CONFIGS = qt_source
IMAGES = $(GUIDIR)/images/filebrowser-01.gif $(GUIDIR)/images/filebrowser-bottom-01.gif $(GUIDIR)/images/png_white_30.png \
$(GUIDIR)/images/record.gif $(GUIDIR)/images/reload.png $(GUIDIR)/images/stop.gif $(GUIDIR)/images/create_folder.png \
$(GUIDIR)/images/divider.png $(GUIDIR)/images/folder.gif $(GUIDIR)/images/help.png $(GUIDIR)/images/quicktime.png \
$(GUIDIR)/images/rec_folder.png $(GUIDIR)/images/up_folder.gif $(GUIDIR)/images/play_audio.png $(GUIDIR)/images/hdd.png
SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c SRCS = camogm.c camogm_ogm.c camogm_jpeg.c camogm_mov.c camogm_kml.c camogm_read.c index_list.c
OBJS = $(SRCS:.c=.o) OBJS = $(SRCS:.c=.o)
...@@ -16,6 +24,7 @@ OWN = -o root -g root ...@@ -16,6 +24,7 @@ OWN = -o root -g root
SYSCONFDIR = /etc/ SYSCONFDIR = /etc/
BINDIR = /usr/bin/ BINDIR = /usr/bin/
WWW_PAGES = /www/pages WWW_PAGES = /www/pages
IMAGEDIR = $(WWW_PAGES)/images
all: $(PROGS) all: $(PROGS)
...@@ -29,6 +38,9 @@ install: $(PROGS) $(PHPSCRIPTS) $(CONFIGS) ...@@ -29,6 +38,9 @@ install: $(PROGS) $(PHPSCRIPTS) $(CONFIGS)
$(INSTALL) $(OWN) -m $(INSTDOCS) $(CONFIGS) $(DESTDIR)$(SYSCONFDIR) $(INSTALL) $(OWN) -m $(INSTDOCS) $(CONFIGS) $(DESTDIR)$(SYSCONFDIR)
$(INSTALL) $(OWN) -d $(DESTDIR)$(WWW_PAGES) $(INSTALL) $(OWN) -d $(DESTDIR)$(WWW_PAGES)
$(INSTALL) $(OWN) -m $(INSTMODE) $(PHPSCRIPTS) $(DESTDIR)$(WWW_PAGES) $(INSTALL) $(OWN) -m $(INSTMODE) $(PHPSCRIPTS) $(DESTDIR)$(WWW_PAGES)
# install camogmgui
$(INSTALL) $(OWN) -d $(DESTDIR)$(IMAGEDIR)
$(INSTALL) $(OWN) -m $(INSTMODE) $(IMAGES) $(DESTDIR)$(IMAGEDIR)
clean: clean:
rm -rf $(PROGS) *.o *~ rm -rf $(PROGS) *.o *~
......
...@@ -1053,7 +1053,7 @@ void camogm_status(camogm_state *state, char * fn, int xml) ...@@ -1053,7 +1053,7 @@ void camogm_status(camogm_state *state, char * fn, int xml)
" <ignore_fps>\"%s\"</ignore_fps>\n" \ " <ignore_fps>\"%s\"</ignore_fps>\n" \
" <raw_device_path>\"%s\"</raw_device_path>\n" \ " <raw_device_path>\"%s\"</raw_device_path>\n" \
" <raw_device_overruns>%d</raw_device_overruns>\n" \ " <raw_device_overruns>%d</raw_device_overruns>\n" \
" <raw_device_pos_write>0x%llx</raw_dev_pos_write>\n" \ " <raw_device_pos_write>0x%llx</raw_device_pos_write>\n" \
" <raw_device_pos_read>0x%llx (%d%% done)</raw_device_pos_read>\n", " <raw_device_pos_read>0x%llx (%d%% done)</raw_device_pos_read>\n",
_state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \ _state, state->path, state->frameno, state->start_after_timestamp, _dur, _udur, _len, \
_frames_skip, _sec_skip, \ _frames_skip, _sec_skip, \
...@@ -1226,11 +1226,9 @@ int parse_cmd(camogm_state *state, FILE* npipe) ...@@ -1226,11 +1226,9 @@ int parse_cmd(camogm_state *state, FILE* npipe)
if (!cmd) return 0; // nothing in the pipe if (!cmd) return 0; // nothing in the pipe
D2(fprintf(debug_file, "Got command: '%s'\n", cmd)); D2(fprintf(debug_file, "Got command: '%s'\n", cmd));
#ifdef DISABLE_CODE
// Acknowledge received command by copying frame number to per-daemon parameter // Acknowledge received command by copying frame number to per-daemon parameter
// GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME); // GLOBALPARS(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num]) = GLOBALPARS(state->port_num, G_THIS_FRAME);
setGValue(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num], getGPValue(state->port_num, G_THIS_FRAME)); setGValue(state->port_num, G_DAEMON_ERR + lastDaemonBit[state->port_num], getGPValue(state->port_num, G_THIS_FRAME));
#endif /* DISABLE_CODE */
args = strpbrk(cmd, "= \t"); args = strpbrk(cmd, "= \t");
// is it just a single word command or does it have parameters? // is it just a single word command or does it have parameters?
if (args) { if (args) {
...@@ -1831,7 +1829,6 @@ int open_files(camogm_state *state) ...@@ -1831,7 +1829,6 @@ int open_files(camogm_state *state)
} }
// now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state) // now open/mmap file to read sensor/compressor parameters (currently - just free memory in circbuf and compressor state)
#ifdef DISABLE_CODE
state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR); state->fd_fparmsall[port] = open(ctlFileNames[port], O_RDWR);
if (state->fd_fparmsall[port] < 0) { // check control OK if (state->fd_fparmsall[port] < 0) { // check control OK
D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port])); D0(fprintf(debug_file, "%s:%d:%s: Error opening %s\n", __FILE__, __LINE__, __FUNCTION__, ctlFileNames[port]));
...@@ -1849,7 +1846,6 @@ int open_files(camogm_state *state) ...@@ -1849,7 +1846,6 @@ int open_files(camogm_state *state)
} }
framePars[port] = frameParsAll[port]->framePars; framePars[port] = frameParsAll[port]->framePars;
aglobalPars[port] = frameParsAll[port]->globalPars; aglobalPars[port] = frameParsAll[port]->globalPars;
#endif /* DISABLE_CODE */
} }
return ret; return ret;
...@@ -1928,12 +1924,9 @@ int main(int argc, char *argv[]) ...@@ -1928,12 +1924,9 @@ int main(int argc, char *argv[])
*/ */
unsigned long getGPValue(unsigned int port, unsigned long GPNumber) unsigned long getGPValue(unsigned int port, unsigned long GPNumber)
{ {
#ifdef DISABLE_CODE
return (GPNumber >= FRAMEPAR_GLOBALS) ? return (GPNumber >= FRAMEPAR_GLOBALS) ?
GLOBALPARS(port, GPNumber) : GLOBALPARS(port, GPNumber) :
framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber]; framePars[port][GLOBALPARS(port, G_THIS_FRAME) & PARS_FRAMES_MASK].pars[GPNumber];
#endif /* DESABLE_CODE */
return 0;
} }
/** /**
......
@charset "UTF-8";
/* SpryCollapsiblePanel.css - Revision: Spry Preview Release 1.4 */
/* Copyright (c) 2006. Adobe Systems Incorporated. All rights reserved. */
/* This is the selector for the main CollapsiblePanel container. For our
* default style, the CollapsiblePanel is responsible for drawing the borders
* around the widget.
*
* If you want to constrain the width of the CollapsiblePanel widget, set a width on
* the CollapsiblePanel container. By default, our CollapsiblePanel expands horizontally to fill
* up available space.
*
* The name of the class ("CollapsiblePanel") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style the
* CollapsiblePanel container.
*/
.CollapsiblePanel {
margin: 0px;
padding: 0px;
border-left: solid 1px #CCC;
border-right: solid 1px #999;
border-top: solid 1px #999;
border-bottom: solid 1px #CCC;
}
/* This is the selector for the CollapsiblePanelTab. This container houses
* the title for the panel. This is also the container that the user clicks
* on to open or close the panel.
*
* The name of the class ("CollapsiblePanelTab") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style an
* CollapsiblePanel panel tab container.
*/
.CollapsiblePanelTab {
font: bold 0.7em sans-serif;
background-color: #DDD;
border-bottom: solid 1px #CCC;
margin: 0px;
padding: 2px;
cursor: pointer;
-moz-user-select: none;
-khtml-user-select: none;
}
/* This is the selector for a CollapsiblePanel's Content area. It's important to note that
* you should never put any padding on the content area element if you plan to
* use the CollapsiblePanel's open/close animations. Placing a non-zero padding on the content
* element can cause the CollapsiblePanel to abruptly grow in height while the panels animate.
*
* The name of the class ("CollapsiblePanelContent") used in this selector is not necessary
* to make the widget function. You can use any class name you want to style a
* CollapsiblePanel content container.
*/
.CollapsiblePanelContent {
margin: 0px;
padding: 0px;
}
/* An anchor tag can be used inside of a CollapsiblePanelTab so that the
* keyboard focus ring appears *inside* the tab instead of around the tab.
* This is an example of how to make the text within the anchor tag look
* like non-anchor (normal) text.
*/
.CollapsiblePanelTab a {
color: black;
text-decoration: none;
}
/* This is an example of how to change the appearance of the panel tab that is
* currently open. The class "CollapsiblePanelOpen" is programatically added and removed
* from panels as the user clicks on the tabs within the CollapsiblePanel.
*/
.CollapsiblePanelOpen .CollapsiblePanelTab {
background-color: #EEE;
}
/* This is an example of how to change the appearance of the panel tab as the
* mouse hovers over it. The class "CollapsiblePanelTabHover" is programatically added
* and removed from panel tab containers as the mouse enters and exits the tab container.
*/
.CollapsiblePanelTabHover, .CollapsiblePanelOpen .CollapsiblePanelTabHover {
background-color: #CCC;
}
/* This is an example of how to change the appearance of all the panel tabs when the
* CollapsiblePanel has focus. The "CollapsiblePanelFocused" class is programatically added and removed
* whenever the CollapsiblePanel gains or loses keyboard focus.
*/
.CollapsiblePanelFocused .CollapsiblePanelTab {
background-color: #3399FF;
}
/* SpryCollapsiblePanel.js - Revision: Spry Preview Release 1.4 */
// Copyright (c) 2006. Adobe Systems Incorporated.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Adobe Systems Incorporated nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
var Spry;
if (!Spry) Spry = {};
if (!Spry.Widget) Spry.Widget = {};
Spry.Widget.CollapsiblePanel = function(element, opts)
{
this.init(element);
Spry.Widget.CollapsiblePanel.setOptions(this, opts);
this.attachBehaviors();
};
Spry.Widget.CollapsiblePanel.prototype.init = function(element)
{
this.element = this.getElement(element);
this.focusElement = null;
this.hoverClass = "CollapsiblePanelTabHover";
this.openClass = "CollapsiblePanelOpen";
this.closedClass = "CollapsiblePanelClosed";
this.focusedClass = "CollapsiblePanelFocused";
this.enableAnimation = true;
this.enableKeyboardNavigation = true;
this.animator = null;
this.hasFocus = false;
this.contentIsOpen = true;
};
Spry.Widget.CollapsiblePanel.prototype.getElement = function(ele)
{
if (ele && typeof ele == "string")
return document.getElementById(ele);
return ele;
};
Spry.Widget.CollapsiblePanel.prototype.addClassName = function(ele, className)
{
if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
return;
ele.className += (ele.className ? " " : "") + className;
};
Spry.Widget.CollapsiblePanel.prototype.removeClassName = function(ele, className)
{
if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))
return;
ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};
Spry.Widget.CollapsiblePanel.prototype.hasClassName = function(ele, className)
{
if (!ele || !className || !ele.className || ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)
return false;
return true;
};
Spry.Widget.CollapsiblePanel.prototype.setDisplay = function(ele, display)
{
if( ele )
ele.style.display = display;
};
Spry.Widget.CollapsiblePanel.setOptions = function(obj, optionsObj, ignoreUndefinedProps)
{
if (!optionsObj)
return;
for (var optionName in optionsObj)
{
if (ignoreUndefinedProps && optionsObj[optionName] == undefined)
continue;
obj[optionName] = optionsObj[optionName];
}
};
Spry.Widget.CollapsiblePanel.prototype.onTabMouseOver = function()
{
this.addClassName(this.getTab(), this.hoverClass);
};
Spry.Widget.CollapsiblePanel.prototype.onTabMouseOut = function()
{
this.removeClassName(this.getTab(), this.hoverClass);
};
Spry.Widget.CollapsiblePanel.prototype.open = function()
{
setCookie('live_image_panel_open', "true", 365);
this.contentIsOpen = true;
if (this.enableAnimation)
{
if (this.animator)
this.animator.stop();
this.animator = new Spry.Widget.CollapsiblePanel.PanelAnimator(this, true);
this.animator.start();
}
else
this.setDisplay(this.getContent(), "block");
this.removeClassName(this.element, this.closedClass);
this.addClassName(this.element, this.openClass);
};
Spry.Widget.CollapsiblePanel.prototype.close = function()
{
setCookie('live_image_panel_open', "false", 365);
this.contentIsOpen = false;
if (this.enableAnimation)
{
if (this.animator)
this.animator.stop();
this.animator = new Spry.Widget.CollapsiblePanel.PanelAnimator(this, false);
this.animator.start();
}
else
this.setDisplay(this.getContent(), "none");
this.removeClassName(this.element, this.openClass);
this.addClassName(this.element, this.closedClass);
};
Spry.Widget.CollapsiblePanel.prototype.onTabClick = function()
{
if (this.isOpen())
this.close();
else
this.open();
this.focus();
};
Spry.Widget.CollapsiblePanel.prototype.onFocus = function(e)
{
this.hasFocus = true;
this.addClassName(this.element, this.focusedClass);
};
Spry.Widget.CollapsiblePanel.prototype.onBlur = function(e)
{
this.hasFocus = false;
this.removeClassName(this.element, this.focusedClass);
};
Spry.Widget.CollapsiblePanel.ENTER_KEY = 13;
Spry.Widget.CollapsiblePanel.SPACE_KEY = 32;
Spry.Widget.CollapsiblePanel.prototype.onKeyDown = function(e)
{
var key = e.keyCode;
if (!this.hasFocus || (key != Spry.Widget.CollapsiblePanel.ENTER_KEY && key != Spry.Widget.CollapsiblePanel.SPACE_KEY))
return true;
if (this.isOpen())
this.close();
else
this.open();
if (e.stopPropagation)
e.stopPropagation();
if (e.preventDefault)
e.preventDefault();
return false;
};
Spry.Widget.CollapsiblePanel.prototype.attachPanelHandlers = function()
{
var tab = this.getTab();
if (!tab)
return;
var self = this;
Spry.Widget.CollapsiblePanel.addEventListener(tab, "click", function(e) { return self.onTabClick(); }, false);
Spry.Widget.CollapsiblePanel.addEventListener(tab, "mouseover", function(e) { return self.onTabMouseOver(); }, false);
Spry.Widget.CollapsiblePanel.addEventListener(tab, "mouseout", function(e) { return self.onTabMouseOut(); }, false);
if (this.enableKeyboardNavigation)
{
// XXX: IE doesn't allow the setting of tabindex dynamically. This means we can't
// rely on adding the tabindex attribute if it is missing to enable keyboard navigation
// by default.
// Find the first element within the tab container that has a tabindex or the first
// anchor tag.
var tabIndexEle = null;
var tabAnchorEle = null;
this.preorderTraversal(tab, function(node) {
if (node.nodeType == 1 /* NODE.ELEMENT_NODE */)
{
var tabIndexAttr = tab.attributes.getNamedItem("tabindex");
if (tabIndexAttr)
{
tabIndexEle = node;
return true;
}
if (!tabAnchorEle && node.nodeName.toLowerCase() == "a")
tabAnchorEle = node;
}
return false;
});
if (tabIndexEle)
this.focusElement = tabIndexEle;
else if (tabAnchorEle)
this.focusElement = tabAnchorEle;
if (this.focusElement)
{
Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "focus", function(e) { return self.onFocus(e); }, false);
Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "blur", function(e) { return self.onBlur(e); }, false);
Spry.Widget.CollapsiblePanel.addEventListener(this.focusElement, "keydown", function(e) { return self.onKeyDown(e); }, false);
}
}
};
Spry.Widget.CollapsiblePanel.addEventListener = function(element, eventType, handler, capture)
{
try
{
if (element.addEventListener)
element.addEventListener(eventType, handler, capture);
else if (element.attachEvent)
element.attachEvent("on" + eventType, handler);
}
catch (e) {}
};
Spry.Widget.CollapsiblePanel.prototype.preorderTraversal = function(root, func)
{
var stopTraversal = false;
if (root)
{
stopTraversal = func(root);
if (root.hasChildNodes())
{
var child = root.firstChild;
while (!stopTraversal && child)
{
stopTraversal = this.preorderTraversal(child, func);
try { child = child.nextSibling; } catch (e) { child = null; }
}
}
}
return stopTraversal;
};
Spry.Widget.CollapsiblePanel.prototype.attachBehaviors = function()
{
var panel = this.element;
var tab = this.getTab();
var content = this.getContent();
if (this.contentIsOpen || this.hasClassName(panel, this.openClass))
{
this.removeClassName(panel, this.closedClass);
this.setDisplay(content, "block");
this.contentIsOpen = true;
}
else
{
this.removeClassName(panel, this.openClass);
this.addClassName(panel, this.closedClass);
this.setDisplay(content, "none");
this.contentIsOpen = false;
}
this.attachPanelHandlers();
};
Spry.Widget.CollapsiblePanel.prototype.getTab = function()
{
return this.getElementChildren(this.element)[0];
};
Spry.Widget.CollapsiblePanel.prototype.getContent = function()
{
return this.getElementChildren(this.element)[1];
};
Spry.Widget.CollapsiblePanel.prototype.isOpen = function()
{
return this.contentIsOpen;
};
Spry.Widget.CollapsiblePanel.prototype.getElementChildren = function(element)
{
var children = [];
var child = element.firstChild;
while (child)
{
if (child.nodeType == 1 /* Node.ELEMENT_NODE */)
children.push(child);
child = child.nextSibling;
}
return children;
};
Spry.Widget.CollapsiblePanel.prototype.focus = function()
{
if (this.focusElement && this.focusElement.focus)
this.focusElement.focus();
};
/////////////////////////////////////////////////////
Spry.Widget.CollapsiblePanel.PanelAnimator = function(panel, doOpen, opts)
{
this.timer = null;
this.interval = 0;
this.stepCount = 0;
this.fps = 0;
this.steps = 10;
this.duration = 500;
this.onComplete = null;
this.panel = panel;
this.content = panel.getContent();
this.panelData = [];
this.doOpen = doOpen;
Spry.Widget.CollapsiblePanel.setOptions(this, opts);
// If caller specified speed in terms of frames per second,
// convert them into steps.
if (this.fps > 0)
{
this.interval = Math.floor(1000 / this.fps);
this.steps = parseInt((this.duration + (this.interval - 1)) / this.interval);
}
else if (this.steps > 0)
this.interval = this.duration / this.steps;
var c = this.content;
var curHeight = c.offsetHeight ? c.offsetHeight : 0;
if (doOpen && c.style.display == "none")
this.fromHeight = 0;
else
this.fromHeight = curHeight;
if (!doOpen)
this.toHeight = 0;
else
{
if (c.style.display == "none")
{
// The content area is not displayed so in order to calculate the extent
// of the content inside it, we have to set its display to block.
c.style.visibility = "hidden";
c.style.display = "block";
}
// Unfortunately in Mozilla/Firefox, fetching the offsetHeight seems to cause
// the browser to synchronously re-layout and re-display content on the page,
// so we see a brief flash of content that is *after* the panel being positioned
// where it should when the panel is fully expanded. To get around this, we
// temporarily position the content area of the panel absolutely off-screen.
// This has the effect of taking the content out-of-flow, so nothing shifts around.
// var oldPos = c.style.position;
// var oldLeft = c.style.left;
// c.style.position = "absolute";
// c.style.left = "-2000em";
// Clear the height property so we can calculate
// the full height of the content we are going to show.
c.style.height = "";
this.toHeight = c.offsetHeight;
// Now restore the position and offset to what it was!
// c.style.position = oldPos;
// c.style.left = oldLeft;
}
this.increment = (this.toHeight - this.fromHeight) / this.steps;
this.overflow = c.style.overflow;
c.style.height = this.fromHeight + "px";
c.style.visibility = "visible";
c.style.overflow = "hidden";
c.style.display = "block";
};
Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.start = function()
{
var self = this;
this.timer = setTimeout(function() { self.stepAnimation(); }, this.interval);
};
Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.stop = function()
{
if (this.timer)
{
clearTimeout(this.timer);
// If we're killing the timer, restore the overflow
// properties on the panels we were animating!
if (this.stepCount < this.steps)
this.content.style.overflow = this.overflow;
}
this.timer = null;
};
Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.stepAnimation = function()
{
++this.stepCount;
this.animate();
if (this.stepCount < this.steps)
this.start();
else if (this.onComplete)
this.onComplete();
};
Spry.Widget.CollapsiblePanel.PanelAnimator.prototype.animate = function()
{
if (this.stepCount >= this.steps)
{
if (!this.doOpen)
this.content.style.display = "none";
this.content.style.overflow = this.overflow;
this.content.style.height = this.toHeight + "px";
}
else
{
this.fromHeight += this.increment;
this.content.style.height = this.fromHeight + "px";
}
};
@charset "UTF-8";
/* SpryTabbedPanels.css - Revision: Spry Preview Release 1.4 */
/* Copyright (c) 2006. Adobe Systems Incorporated. All rights reserved. */
/* Horizontal Tabbed Panels
*
* The default style for a TabbedPanels widget places all tab buttons
* (left aligned) above the content panel.
*/
/* This is the selector for the main TabbedPanels container. For our
* default style, this container does not contribute anything visually,
* but it is floated left to make sure that any floating or clearing done
* with any of its child elements are contained completely within the
* TabbedPanels container, to minimize any impact or undesireable
* interaction with other floated elements on the page that may be used
* for layout.
*
* If you want to constrain the width of the TabbedPanels widget, set a
* width on the TabbedPanels container. By default, the TabbedPanels widget
* expands horizontally to fill up available space.
*
* The name of the class ("TabbedPanels") used in this selector is not
* necessary to make the widget function. You can use any class name you
* want to style the TabbedPanels container.
*/
.TabbedPanels {
margin: 0px;
padding: 0px;
float: left;
clear: none;
width: 100%; /* IE Hack to force proper layout when preceded by a paragraph. (hasLayout Bug)*/
}
/* This is the selector for the TabGroup. The TabGroup container houses
* all of the tab buttons for each tabbed panel in the widget. This container
* does not contribute anything visually to the look of the widget for our
* default style.
*
* The name of the class ("TabbedPanelsTabGroup") used in this selector is not
* necessary to make the widget function. You can use any class name you
* want to style the TabGroup container.
*/
.TabbedPanelsTabGroup {
margin: 0px;
padding: 0px;
}
/* This is the selector for the TabbedPanelsTab. This container houses
* the title for the panel. This is also the tab "button" that the user clicks
* on to activate the corresponding content panel so that it appears on top
* of the other tabbed panels contained in the widget.
*
* For our default style, each tab is positioned relatively 1 pixel down from
* where it wold normally render. This allows each tab to overlap the content
* panel that renders below it. Each tab is rendered with a 1 pixel bottom
* border that has a color that matches the top border of the current content
* panel. This gives the appearance that the tab is being drawn behind the
* content panel.
*
* The name of the class ("TabbedPanelsTab") used in this selector is not
* necessary to make the widget function. You can use any class name you want
* to style this tab container.
*/
.TabbedPanelsTab {
position: relative;
top: 1px;
float: left;
padding: 4px 10px;
margin: 0px 1px 0px 0px;
font: bold 0.7em sans-serif;
background-color: #DDD;
list-style: none;
border-left: solid 1px #CCC;
border-bottom: solid 1px #999;
border-top: solid 1px #999;
border-right: solid 1px #999;
-moz-user-select: none;
-khtml-user-select: none;
cursor: pointer;
}
.TabbedPanelsTabAlert {
position: relative;
top: 1px;
float: left;
padding: 4px 10px;
margin: 0px 1px 0px 0px;
font: bold 0.7em sans-serif;
color:#FF0000;
text-decoration:blink;
list-style: none;
border-left: solid 1px #CCC;
border-bottom: solid 1px #999;
border-top: solid 1px #999;
border-right: solid 1px #999;
-moz-user-select: none;
-khtml-user-select: none;
cursor: pointer;
}
/* This selector is an example of how to change the appearnce of a tab button
* container as the mouse enters it. The class "TabbedPanelsTabHover" is
* programatically added and removed from the tab element as the mouse enters
* and exits the container.
*/
.TabbedPanelsTabHover {
background-color: #CCC;
}
/* This selector is an example of how to change the appearance of a tab button
* container after the user has clicked on it to activate a content panel.
* The class "TabbedPanelsTabSelected" is programatically added and removed
* from the tab element as the user clicks on the tab button containers in
* the widget.
*
* As mentioned above, for our default style, tab buttons are positioned
* 1 pixel down from where it would normally render. When the tab button is
* selected, we change its bottom border to match the background color of the
* content panel so that it looks like the tab is part of the content panel.
*/
.TabbedPanelsTabSelected {
background-color: #EEE;
border-bottom: 1px solid #EEE;
}
/* This selector is an example of how to make a link inside of a tab button
* look like normal text. Users may want to use links inside of a tab button
* so that when it gets focus, the text *inside* the tab button gets a focus
* ring around it, instead of the focus ring around the entire tab.
*/
.TabbedPanelsTab a {
color: black;
text-decoration: none;
}
/* This is the selector for the ContentGroup. The ContentGroup container houses
* all of the content panels for each tabbed panel in the widget. For our
* default style, this container provides the background color and borders that
* surround the content.
*
* The name of the class ("TabbedPanelsContentGroup") used in this selector is
* not necessary to make the widget function. You can use any class name you
* want to style the ContentGroup container.
*/
.TabbedPanelsContentGroup {
clear: both;
border-left: solid 1px #CCC;
border-bottom: solid 1px #CCC;
border-top: solid 1px #999;
border-right: solid 1px #999;
background-color: #EEE;
}
/* This is the selector for the Content panel. The Content panel holds the
* content for a single tabbed panel. For our default style, this container
* provides some padding, so that the content is not pushed up against the
* widget borders.
*
* The name of the class ("TabbedPanelsContent") used in this selector is
* not necessary to make the widget function. You can use any class name you
* want to style the Content container.
*/
.TabbedPanelsContent {
padding: 4px;
margin:2px;
}
/* This selector is an example of how to change the appearnce of the currently
* active container panel. The class "TabbedPanelsContentVisible" is
* programatically added and removed from the content element as the panel
* is activated/deactivated.
*/
.TabbedPanelsContentVisible {
}
/* Vertical Tabbed Panels
*
* The following rules override some of the default rules above so that the
* TabbedPanels widget renders with its tab buttons along the left side of
* the currently active content panel.
*
* With the rules defined below, the only change that will have to be made
* to switch a horizontal tabbed panels widget to a vertical tabbed panels
* widget, is to use the "VTabbedPanels" class on the top-level widget
* container element, instead of "TabbedPanels".
*/
/* This selector floats the TabGroup so that the tab buttons it contains
* render to the left of the active content panel. A border is drawn around
* the group container to make it look like a list container.
*/
.VTabbedPanels .TabbedPanelsTabGroup {
float: left;
width: 10em;
height: 20em;
background-color: #EEE;
position: relative;
border-top: solid 1px #999;
border-right: solid 1px #999;
border-left: solid 1px #CCC;
border-bottom: solid 1px #CCC;
}
/* This selector disables the float property that is placed on each tab button
* by the default TabbedPanelsTab selector rule above. It also draws a bottom
* border for the tab. The tab button will get its left and right border from
* the TabGroup, and its top border from the TabGroup or tab button above it.
*/
.VTabbedPanels .TabbedPanelsTab {
float: none;
margin: 0px;
border-top: none;
border-left: none;
border-right: none;
}
/* This selector disables the float property that is placed on each tab button
* by the default TabbedPanelsTab selector rule above. It also draws a bottom
* border for the tab. The tab button will get its left and right border from
* the TabGroup, and its top border from the TabGroup or tab button above it.
*/
.VTabbedPanels .TabbedPanelsTabSelected {
background-color: #EEE;
border-bottom: solid 1px #999;
}
/* This selector floats the content panels for the widget so that they
* render to the right of the tabbed buttons.
*/
.VTabbedPanels .TabbedPanelsContentGroup {
clear: none;
float: left;
padding: 0px;
width: 30em;
height: 20em;
}
/* SpryTabbedPanels.js - Revision: Spry Preview Release 1.4 */
// Copyright (c) 2006. Adobe Systems Incorporated.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Adobe Systems Incorporated nor the names of its
// contributors may be used to endorse or promote products derived from this
// software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
var Spry;
if (!Spry) Spry = {};
if (!Spry.Widget) Spry.Widget = {};
Spry.Widget.TabbedPanels = function(element, opts)
{
this.element = this.getElement(element);
this.defaultTab = 0; // Show the first panel by default.
this.bindings = [];
this.tabSelectedClass = "TabbedPanelsTabSelected";
this.tabHoverClass = "TabbedPanelsTabHover";
this.tabFocusedClass = "TabbedPanelsTabFocused";
this.panelVisibleClass = "TabbedPanelsContentVisible";
this.focusElement = null;
this.hasFocus = false;
this.currentTabIndex = 0;
this.enableKeyboardNavigation = true;
Spry.Widget.TabbedPanels.setOptions(this, opts);
// If the defaultTab is expressed as a number/index, convert
// it to an element.
if (typeof (this.defaultTab) == "number")
{
if (this.defaultTab < 0)
this.defaultTab = 0;
else
{
var count = this.getTabbedPanelCount();
if (this.defaultTab >= count)
this.defaultTab = (count > 1) ? (count - 1) : 0;
}
this.defaultTab = this.getTabs()[this.defaultTab];
}
// The defaultTab property is supposed to be the tab element for the tab content
// to show by default. The caller is allowed to pass in the element itself or the
// element's id, so we need to convert the current value to an element if necessary.
if (this.defaultTab)
this.defaultTab = this.getElement(this.defaultTab);
this.attachBehaviors();
};
Spry.Widget.TabbedPanels.prototype.getElement = function(ele)
{
if (ele && typeof ele == "string")
return document.getElementById(ele);
return ele;
}
Spry.Widget.TabbedPanels.prototype.getElementChildren = function(element)
{
var children = [];
var child = element.firstChild;
while (child)
{
if (child.nodeType == 1 /* Node.ELEMENT_NODE */)
children.push(child);
child = child.nextSibling;
}
return children;
};
Spry.Widget.TabbedPanels.prototype.addClassName = function(ele, className)
{
if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))
return;
ele.className += (ele.className ? " " : "") + className;
};
Spry.Widget.TabbedPanels.prototype.removeClassName = function(ele, className)
{
if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))
return;
ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");
};
Spry.Widget.TabbedPanels.setOptions = function(obj, optionsObj, ignoreUndefinedProps)
{
if (!optionsObj)
return;
for (var optionName in optionsObj)
{
if (ignoreUndefinedProps && optionsObj[optionName] == undefined)
continue;
obj[optionName] = optionsObj[optionName];
}
};
Spry.Widget.TabbedPanels.prototype.getTabGroup = function()
{
if (this.element)
{
var children = this.getElementChildren(this.element);
if (children.length)
return children[0];
}
return null;
};
Spry.Widget.TabbedPanels.prototype.getTabs = function()
{
var tabs = [];
var tg = this.getTabGroup();
if (tg)
tabs = this.getElementChildren(tg);
return tabs;
};
Spry.Widget.TabbedPanels.prototype.getContentPanelGroup = function()
{
if (this.element)
{
var children = this.getElementChildren(this.element);
if (children.length > 1)
return children[1];
}
return null;
};
Spry.Widget.TabbedPanels.prototype.getContentPanels = function()
{
var panels = [];
var pg = this.getContentPanelGroup();
if (pg)
panels = this.getElementChildren(pg);
return panels;
};
Spry.Widget.TabbedPanels.prototype.getIndex = function(ele, arr)
{
ele = this.getElement(ele);
if (ele && arr && arr.length)
{
for (var i = 0; i < arr.length; i++)
{
if (ele == arr[i])
return i;
}
}
return -1;
};
Spry.Widget.TabbedPanels.prototype.getTabIndex = function(ele)
{
var i = this.getIndex(ele, this.getTabs());
if (i < 0)
i = this.getIndex(ele, this.getContentPanels());
return i;
};
Spry.Widget.TabbedPanels.prototype.getCurrentTabIndex = function()
{
return this.currentTabIndex;
};
Spry.Widget.TabbedPanels.prototype.getTabbedPanelCount = function(ele)
{
return Math.min(this.getTabs().length, this.getContentPanels().length);
};
Spry.Widget.TabbedPanels.addEventListener = function(element, eventType, handler, capture)
{
try
{
if (element.addEventListener)
element.addEventListener(eventType, handler, capture);
else if (element.attachEvent)
element.attachEvent("on" + eventType, handler);
}
catch (e) {}
};
Spry.Widget.TabbedPanels.prototype.onTabClick = function(e, tab)
{
this.showPanel(tab);
if (typeof tab == "number")
Index = tab;
else // Must be the element for the tab or content panel.
Index = this.getTabIndex(tab);
setCookie('tab', Index, 365);
};
Spry.Widget.TabbedPanels.prototype.onTabMouseOver = function(e, tab)
{
this.addClassName(tab, this.tabHoverClass);
};
Spry.Widget.TabbedPanels.prototype.onTabMouseOut = function(e, tab)
{
this.removeClassName(tab, this.tabHoverClass);
};
Spry.Widget.TabbedPanels.prototype.onTabFocus = function(e, tab)
{
this.hasFocus = true;
this.addClassName(this.element, this.tabFocusedClass);
};
Spry.Widget.TabbedPanels.prototype.onTabBlur = function(e, tab)
{
this.hasFocus = false;
this.removeClassName(this.element, this.tabFocusedClass);
};
Spry.Widget.TabbedPanels.ENTER_KEY = 13;
Spry.Widget.TabbedPanels.SPACE_KEY = 32;
Spry.Widget.TabbedPanels.prototype.onTabKeyDown = function(e, tab)
{
var key = e.keyCode;
if (!this.hasFocus || (key != Spry.Widget.TabbedPanels.ENTER_KEY && key != Spry.Widget.TabbedPanels.SPACE_KEY))
return true;
this.showPanel(tab);
if (e.stopPropagation)
e.stopPropagation();
if (e.preventDefault)
e.preventDefault();
return false;
};
Spry.Widget.TabbedPanels.prototype.preorderTraversal = function(root, func)
{
var stopTraversal = false;
if (root)
{
stopTraversal = func(root);
if (root.hasChildNodes())
{
var child = root.firstChild;
while (!stopTraversal && child)
{
stopTraversal = this.preorderTraversal(child, func);
try { child = child.nextSibling; } catch (e) { child = null; }
}
}
}
return stopTraversal;
};
Spry.Widget.TabbedPanels.prototype.addPanelEventListeners = function(tab, panel)
{
var self = this;
Spry.Widget.TabbedPanels.addEventListener(tab, "click", function(e) { return self.onTabClick(e, tab); }, false);
Spry.Widget.TabbedPanels.addEventListener(tab, "mouseover", function(e) { return self.onTabMouseOver(e, tab); }, false);
Spry.Widget.TabbedPanels.addEventListener(tab, "mouseout", function(e) { return self.onTabMouseOut(e, tab); }, false);
if (this.enableKeyboardNavigation)
{
// XXX: IE doesn't allow the setting of tabindex dynamically. This means we can't
// rely on adding the tabindex attribute if it is missing to enable keyboard navigation
// by default.
// Find the first element within the tab container that has a tabindex or the first
// anchor tag.
var tabIndexEle = null;
var tabAnchorEle = null;
this.preorderTraversal(tab, function(node) {
if (node.nodeType == 1 /* NODE.ELEMENT_NODE */)
{
var tabIndexAttr = tab.attributes.getNamedItem("tabindex");
if (tabIndexAttr)
{
tabIndexEle = node;
return true;
}
if (!tabAnchorEle && node.nodeName.toLowerCase() == "a")
tabAnchorEle = node;
}
return false;
});
if (tabIndexEle)
this.focusElement = tabIndexEle;
else if (tabAnchorEle)
this.focusElement = tabAnchorEle;
if (this.focusElement)
{
Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "focus", function(e) { return self.onTabFocus(e, tab); }, false);
Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "blur", function(e) { return self.onTabBlur(e, tab); }, false);
Spry.Widget.TabbedPanels.addEventListener(this.focusElement, "keydown", function(e) { return self.onTabKeyDown(e, tab); }, false);
}
}
};
Spry.Widget.TabbedPanels.prototype.showPanel = function(elementOrIndex)
{
var tpIndex = -1;
if (typeof elementOrIndex == "number")
tpIndex = elementOrIndex;
else // Must be the element for the tab or content panel.
tpIndex = this.getTabIndex(elementOrIndex);
if (!tpIndex < 0 || tpIndex >= this.getTabbedPanelCount())
return;
var tabs = this.getTabs();
var panels = this.getContentPanels();
var numTabbedPanels = Math.max(tabs.length, panels.length);
for (var i = 0; i < numTabbedPanels; i++)
{
if (i != tpIndex)
{
if (tabs[i])
this.removeClassName(tabs[i], this.tabSelectedClass);
if (panels[i])
{
this.removeClassName(panels[i], this.panelVisibleClass);
panels[i].style.display = "none";
}
}
}
this.addClassName(tabs[tpIndex], this.tabSelectedClass);
this.addClassName(panels[tpIndex], this.panelVisibleClass);
panels[tpIndex].style.display = "block";
this.currentTabIndex = tpIndex;
};
Spry.Widget.TabbedPanels.prototype.attachBehaviors = function(element)
{
var tabs = this.getTabs();
var panels = this.getContentPanels();
var panelCount = this.getTabbedPanelCount();
for (var i = 0; i < panelCount; i++)
this.addPanelEventListeners(tabs[i], panels[i]);
this.showPanel(this.defaultTab);
};
<?
/*!***************************************************************************
*! FILE NAME : camogmgui.php
*! DESCRIPTION: command interface for the camogm recorder and camogm GUI
*! Copyright (C) 2008 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: camogm_interface.php,v $
*! Revision 1.23 2013/05/28 01:49:19 dzhimiev
*! 1. fixed list-command
*!
*! Revision 1.22 2013/05/26 04:41:32 dzhimiev
*! 1. minor changes to avoid php hanging when not communicating with camogm
*!
*! Revision 1.21 2012/04/14 01:25:12 dzhimiev
*! 1. added 'list' - shows files at the specified path
*!
*! Revision 1.20 2011/06/02 12:29:07 oneartplease
*! added new option to set_start_after_timestamp to allow setting record start time in the future without first having to read current camera time "p5" as parameter will start recording at camera time "p"lus 5 seconds
*!
*! Revision 1.19 2011/04/04 20:19:36 dzhimiev
*! 1. added frame skipping option
*!
*! Revision 1.18 2011/01/01 13:04:47 oneartplease
*! added commands to set frameskipping and secondsskipping (timelapse)
*!
*! Revision 1.17 2010/08/20 20:16:55 oneartplease
*! cleaned up setcookie commands
*!
*! Revision 1.16 2010/08/08 20:19:46 dzhimiev
*! 1. added write/read elphel parameters
*! 2. camogm: debuglev , start_after_timestamp
*!
*! Revision 1.15 2010/06/24 17:31:55 dzhimiev
*! 1. added camogm process run check (ps | grep camogm)
*!
*! Revision 1.14 2010/01/19 10:07:20 oneartplease
*! added unmounting command
*!
*! Revision 1.12 2009/10/13 12:42:31 oneartplease
*! moved save_gp=1 command
*!
*! Revision 1.11 2009/06/24 15:20:04 oneartplease
*! file renaming works with absolute paths now as preparation for mounting multiple devices
*!
*! Revision 1.5 2009/03/26 12:20:40 oneartplease
*! audio and geotagging updates, both are not fully working yet though
*!
*! Revision 1.9 2009/01/14 08:26:19 oneartplease
*! minor updates
*!
*!
*! Revision 1.0 2008/09/21 Sebastian Pichelhofer
*! start and stop commands for ajax execution
*!
*/
$cmd = $_GET['cmd'];
$debug = $_GET['debug'];
$debuglev = $_GET['debuglev'];
$cmd_pipe = "/var/state/camogm_cmd";
$cmd_port = "3456";
$start_str = "camogm -n " . $cmd_pipe . " -p " . $cmd_port;
if ($cmd == "run_camogm")
{
$camogm_running = false;
exec('ps | grep "camogm"', $arr);
function low_daemon($v)
{
return (substr($v, -1) != ']');
}
$p = (array_filter($arr, "low_daemon"));
$check = implode("<br />",$p);
if (strstr($check, $start_str))
$camogm_running = true;
else
$camogm_running = false;
if(!$camogm_running) {
exec("rm /var/state/camogm.state");
if (!$debug) exec($start_str.' > /dev/null 2>&1 &'); // "> /dev/null 2>&1 &" makes sure it is really really run as a background job that does not wait for input
else exec($start_str.$debug.' 2>&1 &');
for($i=0;$i<5;$i++) {
if (is_file("/var/state/camogm.state")) break;
sleep(1);
}
if ($debug) {
$fcmd = fopen($cmd_pipe, "w");
fprintf($fcmd,"debuglev=$debuglev");
}
}
}
else if ($cmd == "status")
{
$pipe="/var/state/camogm.state";
$mode=0777;
if(!file_exists($pipe)) {
umask(0);
posix_mkfifo($pipe,$mode);
}
$fcmd=fopen($cmd_pipe,"w");
fprintf($fcmd, "xstatus=%s\n",$pipe);
fclose($fcmd);
$status=file_get_contents($pipe);
header("Content-Type: text/xml");
header("Content-Length: ".strlen($status)."\n");
header("Pragma: no-cache\n");
printf("%s", $status);
}
else if ($cmd == "run_status")
{
// is camogm running
$camogm_running = "not running";
exec('ps | grep "camogm"', $arr);
function low_daemon($v)
{
return (substr($v, -1) != ']');
}
$p = (array_filter($arr, "low_daemon"));
$check = implode("<br />",$p);
if (strstr($check, $start_str))
$camogm_running = "on";
else
$camogm_running = "off";
$status="<?xml version='1.0'?><camogm_state>\n<state>".$camogm_running."</state>\n</camogm_state>";
header("Content-Type: text/xml");
header("Content-Length: ".strlen($status)."\n");
header("Pragma: no-cache\n");
printf("%s", $status);
}
else if ($cmd=="get_hdd_space"){
if (isset($_GET['mountpoint']))
$mountpoint = $_GET['mountpoint'];
else
$mountpoint = '/mnt/sda1';
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo disk_free_space($mountpoint);
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="mount") { // mount media like HDD
if (isset($_GET['partition']))
$partition = $_GET['partition'];
else
$partition = '/dev/sda1';
//$partition = '/dev/hda1';
if (isset($_GET['mountpoint']))
$mountpoint = $_GET['mountpoint'];
else
$mountpoint = '/var/hdd';
exec('mkdir '.$mountpoint);
//exec('mkdir /var/hdd');
exec('mount '.$partition." ".$mountpoint);
//exec('mount /dev/hda1 /var/hdd');
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo "done";
echo "</".$cmd.">";
xml_footer();
}
else if (($cmd=="umount") || ($cmd=="unmount")) { // unmount media like HDD
$message = "";
if (isset($_GET['mountpoint'])) {
$mountpoint = $_GET['mountpoint'];
exec('umount '.$mountpoint);
$message = "done";
} else {
$message = "missing argument: mountpoint";
}
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo $message;
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="set_quality") {
$quality = $_GET['quality'];
$thisFrameNumber=elphel_get_frame();
elphel_set_P_value(ELPHEL_QUALITY,$quality+0,$thisFrameNumber);
//$thisFrameNumber=elphel_get_frame();
//elphel_wait_frame_abs($thisFrameNumber+3);
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo elphel_get_P_value(ELPHEL_QUALITY);
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="get_quality") {
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo elphel_get_P_value(ELPHEL_QUALITY);
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="set_parameter") {
$pname = $_GET['pname'];
$pvalue = $_GET['pvalue'];
$thisFrameNumber=elphel_get_frame();
$constant=constant("ELPHEL_$pname");
elphel_set_P_value($constant,$pvalue+0,$thisFrameNumber);
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo elphel_get_P_value($constant);
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="get_parameter") {
$pname = $_GET['pname'];
$constant=constant("ELPHEL_$pname");
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo elphel_get_P_value($constant);
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="set_skip") {
$skipping_mask = $_GET['skip_mask'];
exec("fpcf -w 4d $skipping_mask");
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo "done";
echo "</".$cmd.">";
xml_footer();
}
else if ($cmd=="list") {
if (isset($_GET['path'])) $path = $_GET['path'];
else {
$message = "the path is not set";
break;
}
if (is_dir($path)) {
$files = scandir($path);
foreach ($files as $file){
if (is_file("$path/$file")) $message .= "<f>$path/$file</f>\n";
}
}else{
$message = "directory not found";
break;
}
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
echo $message;
echo "</".$cmd.">";
xml_footer();
}
else
{
$fcmd = fopen($cmd_pipe, "w");
xml_header();
echo "<command>".$cmd."</command>";
echo "<".$cmd.">";
switch ($cmd)
{
case "start":
fprintf($fcmd,"start;\n");
break;
case "stop":
fprintf($fcmd,"stop;\n");
exec('sync');
break;
case "exit":
fprintf($fcmd,"exit;\n");
exec('sync');
break;
case "file_rename":
// Now requires full path (like "/var/hdd/test1.mov") for file_old
// and either a full path or just a filename for file_new
if ((!isset($_GET['file_old'])) || (!isset($_GET['file_new']))) {
echo "wrong arguments";
break;
}
$old_name = $_GET['file_old'];
$new_name = $_GET['file_new'];
if (!strrpos($new_name, "/")) {
$new_name = substr($old_name, 0, strrpos($old_name, "/")+1).$new_name;
}
if ($old_name == $new_name) {
echo "filenames match";
break;
}
if (file_exists($new_name)) {
echo "file_new already exists";
break;
}
if (!file_exists($old_name)) {
echo "file_old does not exist";
break;
}
// no errors found, so do the rename
if (rename($old_name, $new_name))
echo "done";
else
echo "undefined error";
break;
case "listdevices":
exec ("cat /proc/partitions", $arr1);
exec ("cat /proc/mounts", $arr2);
$j = 0;
// first two lines are header and empty line separator, skip them
$i = 2;
while($i < count($arr1)) {
// skip flash and RAM disk partitions
if (!strpos($arr1[$i], "mtdblock") && !strpos($arr1[$i], "ram")) {
$temp = $arr1[$i];
while(strstr($temp, " ")) {
$temp = str_replace(chr(9), " ", $temp);
$temp = str_replace(" ", " ", $temp);
}
if (preg_match_all('/ +[a-z]{3,3}[0-9]{1,1}$/', $temp, $available_partitons) > 0) {
// remove leading spaces
$partitions[$j] = preg_replace("/^ +/", "", $available_partitons[0][0]);
$parts = explode(" ", $temp);
$size[$j] = $parts[3];
$j++;
}
}
$i++;
}
$j = 0;
foreach ($partitions as $partition) {
echo "<item>";
echo "<partition>/dev/".$partition."</partition>";
echo "<size>".round($size[$j]/1024/1024, 2) ." GB</size>";
$j++;
$i = 0;
while($i < count($arr2)) {
if(strpos($arr2[$i], $partition))
{
$parts = explode(" ", $arr2[$i]);
$mountpoint = $parts[1];
$filesystem = $parts[2];
}
$i++;
}
if ($mountpoint != "") {
echo "<mountpoint>".$mountpoint."</mountpoint>";
$mountpoint = "";
} else {
echo "<mountpoint>none</mountpoint>";
}
if ($filesystem != "") {
echo "<filesystem>".$filesystem."</filesystem>";
$filesystem = "";
} else {
echo "<filesystem>none</filesystem>";
}
echo "</item>";
}
break;
case "mkdir":
$dir_name = $_GET['name'];
if (isset($dir_name) && (($dir_name != "") || ($dir_name != " ")))
{
exec('mkdir /var/hdd/'.$dir_name);
echo "done";
break;
}
else
break;
case "is_hdd_mounted":
if (isset($_GET['partition']))
$partition = $_GET['partition'];
else
$partition = '/dev/sda1';
//$partition = '/dev/hda1';
exec('mount', $arr);
$mounted = implode("", $arr);
if (strstr($mounted, $partition))
echo substr($mounted, strpos($mounted, $partition),22);
else
echo "no HDD mounted";
break;
case "create_symlink":
//exec('ln -s /var/hdd /mnt/flash/html/hdd');
if (isset($_GET['mountpoint'])) $mountpoint = $_GET['mountpoint'];
else $mountpoint = "/mnt/sda1";
exec("rm /www/pages/hdd");
exec("ln -sf $mountpoint /www/pages/hdd");
break;
// case "list":
// if (isset($_GET['path'])) $path = $_GET['path'];
// else {
// echo "the path is not set";
// break;
// }
//
// if (is_dir($path)) {
// $files = scandir($path);
// foreach ($files as $file){
// if (is_file("$path/$file")) echo "<f>$path/$file</f>";
// }
// }else{
// echo "directory not found";
// break;
// }
//
// break;
case "list_files":
if (!file_exists('/www/pages/hdd')) {
echo "no webshare found";
break;
}
$dir = $_GET["dir"];
if (isset($dir) && ($dir != "") && ($dir != "/./") && ($dir != "/")) // show "one level up" item if we are not in "home" directory
{
echo "<file>";
echo "<type>updir</type>";
echo "<name>..</name>";
$file_remove_last_slash = substr($dir, 0, strlen($dir)-1);
$file_pos_of_second_last_slash = strrpos($file_remove_last_slash, "/");
$up_file = substr($dir, 0, $file_pos_of_second_last_slash+1);
while(strpos($up_file, "//")) {
$up_file = str_replace("//", "/", $up_file);
}
if ($up_file == "")
echo "<path>/</path>";
else
echo "<path>".$up_file."</path>";
echo "<size>0</size>";
echo "<date>0</date>";
echo "</file>";
}
if ($handle = opendir('/www/pages/hdd/'.$dir)) {
while ($file = readdir($handle))
{
if ($file != "." && $file != "..")
{
echo "<file>";
echo "<type>";
if (is_dir("/www/pages/hdd/".$dir.$file))
echo "dir";
else
echo $extension = substr($file, strrpos($file, '.')+1, strlen($file));
echo "</type>";
echo "<name>".$file."</name>";
echo "<path>".substr($dir, 1).$file."</path>";
$size = filesize("/www/pages/hdd/".$dir.$file);
echo "<size>".$size."</size>";
if(!ini_get('date.timezone')){
date_default_timezone_set('GMT');
}
$date = date ("d M Y H:i:s", filectime("/www/pages/hdd/".$dir.$file));
echo "<date>".$date."</date>";
echo "</file>";
}
}
closedir($handle);
}else{
echo "no webshare found<br>";
}
break;
case "set_prefix":
$prefix = $_GET['prefix'];
fprintf($fcmd, "prefix=%s;\n", $prefix);
setcookie("directory", $prefix);
break;
case "set_debuglev":
$debuglev = $_GET['debuglev'];
fprintf($fcmd, "debuglev=%s;\n", $debuglev);
break;
case "set_duration":
$duration = $_GET['duration'];
fprintf($fcmd, "duration=%s;\n", $duration);
break;
case "set_size":
$size = $_GET['size'];
fprintf($fcmd, "length=%s;\n", $size);
break;
case "set_max_frames":
$max_frames = $_GET['max_frames'];
fprintf($fcmd, "max_frames=%s;\n", $max_frames);
break;
case "set_frames_per_chunk":
$frames_per_chunk = $_GET['frames_per_chunk'];
fprintf($fcmd, "frames_per_chunk=%s;\n", $frames_per_chunk);
break;
case "set_start_after_timestamp":
$start_after_timestamp = $_GET['start_after_timestamp'];
// Allow setting start timestamp as relative time with "p3" = plus 3 second
// This allows triggering recording in the future without first reading current camera time
if (substr($start_after_timestamp, 0, 1) == "p") {
$start_after_timestamp = elphel_get_fpga_time() + substr($start_after_timestamp, 1) ;
//echo "now: ".elphel_get_fpga_time()." relative: ".$start_after_timestamp; //debug
}
fprintf($fcmd, "start_after_timestamp=%s;\n", $start_after_timestamp);
break;
case "set_frameskip":
$frameskip_value = $_GET['frameskip'];
fprintf($fcmd, "frameskip=%s;\n", $frameskip_value);
break;
case "set_timelapse":
$timelapse_value = $_GET['timelapse'];
fprintf($fcmd, "timelapse=%s;\n", $timelapse_value);
break;
case "init_compressor":
$sensor_port = $_GET['sensor_port'];
elphel_compressor_run($sensor_port);
break;
case "check_audio_hardware":
exec('arecord -l', $arr1);
$audio_hardware = implode("", $arr1);
if ($audio_hardware == "")
echo "no Audio Hardware detected";
else
{
$message = substr($audio_hardware, strpos($audio_hardware, "],")+2);
$message = substr($message, 1, strpos($message, "[")-2);
echo $message;
}
break;
case "test_audio_playback":
$soundfile = $_GET['soundfile'];
exec('aplay '.$soundfile);
break;
case "setmov":
exec('echo "format=mov;" > /var/state/camogm_cmd'); // Set quicktime *.mov as default format after startup.
exec('echo "save_gp=1;\n" > /var/state/camogm_cmd'); // enable calculation of free/used buffer space
break;
case "setjpeg":
exec('echo "format=jpg;" > /var/state/camogm_cmd'); // Set quicktime *.mov as default format after startup.
exec('echo "save_gp=1;\n" > /var/state/camogm_cmd'); // enable calculation of free/used buffer space
break;
case "gettime":
echo elphel_get_fpga_time();
break;
}
if ($fcmd)
fclose($fcmd);
echo "</".$cmd.">";
xml_footer();
}
function xml_header() {
header("Content-type: text/xml");
header("Pragma: no-cache\n");
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n";
echo "<camogm_interface>\n";
}
function xml_footer() {
echo "</camogm_interface>\n";
}
?>
html {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
font-style: normal;
text-decoration: none;
border: 0px;
background-color:#f9fcfc;
}
table td {
font-size: 12px;
}
body {
margin:10px;
}
a {
color:#09284a;
}
a:hover {
color:#09708a;
}
#help_link a{
float:right;
display:inline;
text-transform:capitalize;
letter-spacing:3px;
color:#000066;
margin-right:8px;
text-decoration:none;
font-weight:bold;
}
#sitecoloumn {
background-color:#F4F4F2;
border:1px solid #AFACAC;
margin-left:auto;
margin-right:auto;
position:relative;
padding-bottom:5px;
top:5px;
width:950px;
height:auto;
}
#header {
font-size:14px;
font-weight:bold;
color:#000;
margin:3px;
text-align:center;
}
.small {
font-size:10px;
color:#888;
}
img {
border:0;
}
#live-image {
text-align:center;
padding:2px;
margin:3px;
}
#live-image-header {
background-color:#efece7;
border:solid 1px #eee;
font-size:9px;
border-bottom:solid 1px #aaa;
}
#live-image-header td {
font-size:9px;
}
#live-image-header a {
color:#000;
text-decoration:none;
font-size:9px;
}
#live-image-header a:hover {
color:#000;
font-size:9px;
background-image:url(images/png_white_30.png);
background-repeat:repeat;
padding:2px;
left:-3px;
position:relative;
border:solid 1px #3A3A3A;
text-decoration:none;
}
#files {
border:1px;
border-style: solid;
padding:0px;
width:500px;
left:5px;
height:372px;
position:relative;
background-color:#f2f7fd;
}
#filelist {
width:500px;
top:26px;
height:320px;
position:absolute;
overflow:auto;
}
#files_header {
background-image:url(images/filebrowser-01.gif);
background-repeat:repeat-x;
height:25px;
color:#FFFFFF;
padding:3px;
}
#files_footer {
padding:5px;
height:25px;
bottom:-10px;
position:absolute;
width:490px;
color:#ffffff;
background-image:url(images/filebrowser-bottom-01.gif);
background-repeat:repeat-x;
}
#files_current_folder {
color:#ffffff;
right:10px;
position:absolute;
}
.file_row_even {
background-color:#EAEDF2;
}
.file_row_odd {
background-color:#D8DBE2;
}
#file_browser_commands {
position:absolute;
padding:2px;
right:-120px;
top:0px;
width:430px;
height:30px;
}
#file_browser_commands a {
color:#FFFFFF;
text-decoration:none;
}
#file_browser_commands a:hover {
color:#000;
background-image:url(images/png_white_30.png);
background-repeat:repeat;
padding:2px;
left:-3px;
position:relative;
border:solid 1px #3A3A3A;
text-decoration:none;
}
#TabbedPanels1 {
width:422px;
}
#record a{
position:absolute;
width:410px;
text-decoration:none;
font-weight:bold;
height:30px;
background:#b50000;
color:#FFFFFF;
text-align:center;
padding:5px;
border:2px outset #fff;
}
#record a:hover{
background:#980000;
}
.alert {
color: red;
}
.green {
color:#009900;
}
table.state_table {
color:#999999;
width:380px;
margin: 0px;
padding: 0px;
border-width: 0px;
border-spacing: 0px;
border-style: solid solid solid solid;
border-color: gray gray gray gray;
border-collapse:collapse;
}
table.state_table td {
border-width: 0px;
padding: 2px 2px 2px 2px;
border-style: solid solid solid solid;
border-color: black black black black;
-moz-border-radius: 0px 0px 0px 0px;
}
#advanced_name_panel {
}
#buffer_toggle {
position:absolute;
right:30px;
padding-right:40px;
}
#buffer_bar {
right:50px;
margin-right:8px;
width:340px;
height:15px;
border:1px solid #0066FF;
position:absolute;
padding:1px;
}
#buffer_free {
background-color:#009900;
margin-left:5px;
height:15px;
position:absolute;
width:260px;
display:inline;
float:left;
text-align:center;
color:#FFFFFF;
letter-spacing:3px;
}
#buffer_used {
background-color:#CC0000;
height:15px;
position:absolute;
width:40px;
display:inline;
float:right;
right:1px;
text-align:center;
color:#FFFFFF;
letter-spacing:3px;
}
#ajax_devices {
border:solid 1px #444;
background-color:white;
}
.sensor_ports * {
vertical-align: middle;
margin-left: 5px;
margin-right: 5px;
margin-top: 0px;
margin-bottom: 0px;
}
#live_image_auto_update_frequency {
height: 18px;
font-size: 9px;
margin: 0px;
padding: 0px;
}
#live_image_auto_update {
margin: 0px;
padding: 0px;
}
\ No newline at end of file
function timer_functions(){
list_files(getCookie("current_dir"));
update_state();
is_hdd_mounted();
}
var global_timer;
function init() {
//setTimeout('is_hdd_mounted()', 300);
if (document.format.container[2].checked){
//setTimeout('format_changed(document.format.container[2])', 600);
format_changed(document.format.container[2]);
}
//setTimeout('update_name_scheme()', 900);
//setTimeout('check_audio_hardware()', 1200);
//setTimeout('update_audio_form(document.getElementById("audioform"))', 1500);
//setTimeout('calc_split_size()', 2300);
//setTimeout('scan_devices()', 3000);
update_name_scheme();
check_audio_hardware();
update_audio_form(document.getElementById("audioform"));
calc_split_size();
//calling "is_mounted" at response
scan_devices("is_mounted(selected_device)");
//global_timer = setInterval(timer_functions,2000);
}
function reload() {
makeRequest('camogm_interface.php', '?cmd=run_camogm');
setTimeout('makeRequest("camogm_interface.php", "?cmd=setmov")', 500); // set MOV as default container format
}
function mount_hdd(callback) {
makeRequest('camogm_interface.php','?cmd=mount',callback);
document.getElementById('directory').value = "/var/hdd/";
document.getElementById('mount_hdd_button').style.display = "none";
}
function process_mount_hdd(xmldoc) {
var response = xmldoc.getElementsByTagName('mount')[0].firstChild.data;
if (response == "done")
{
//setTimeout('is_hdd_mounted()', 500);
scan_devices("is_mounted(selected_device)");
console.log("mounted");
}
}
function mount_custom_partition(partition) {
if (document.getElementById("mount_point").value != "") {
makeRequest('camogm_interface.php','?cmd=mount&partition='+partition+'&mountpoint='+document.getElementById("mount_point").value,"scan_devices()");
document.getElementById('directory').value = "/var/hdd/";
document.getElementById('mount_hdd_button').style.display = "none";
}
}
function unmount_custom_partition(mountpoint) {
if (mountpoint != "") {
//calling back scan_devices()
makeRequest('camogm_interface.php','?cmd=umount&mountpoint='+mountpoint,"scan_devices(list_files(\"\"))");
}
}
function is_hdd_mounted() {
makeRequest('camogm_interface.php','?cmd=is_hdd_mounted');
}
function is_mounted(dev,callback){
makeRequest('camogm_interface.php','?cmd=is_hdd_mounted&partition='+dev,callback);
}
function nothing_is_mounted_hide(){
document.getElementById('mounted_devices').innerHTML = "no devices found";
document.getElementById('refresh_file_list').style.display = "none"; // hide "reload" button
document.getElementById('create_webshare_button').style.display = "none"; // hide "create webshare" button
document.getElementById('create_folder').style.display = "none"; // hide "create folder" button
document.getElementById('set_rec_dir').style.display = "none"; // hide "set record directory" button
document.getElementById('mount_hdd_button').style.display = 'none';
}
function process_is_hdd_mounted(xmldoc) {
var response = xmldoc.getElementsByTagName('is_hdd_mounted')[0].firstChild.data;
if (response == "no HDD mounted")
{
nothing_is_mounted_hide();
// Ignore all odds and just mount it
//setTimeout('mount_hdd()', 1000);
mount_hdd();
}
else // we have a hdd mounted
{
document.getElementById('mount_hdd_button').style.display = 'none'; // hide mount button
document.getElementById('refresh_file_list').style.display = "inline"; // show "reload" button
document.getElementById('create_webshare_button').style.display = "inline"; // show "create webshare" button
document.getElementById('create_folder').style.display = "inline"; // show "create folder" button
document.getElementById('set_rec_dir').style.display = "inline"; // show "set record directory" button
document.getElementById('mounted_devices').innerHTML = response;
mountpoint = response.substring(response.indexOf(" on ")+4);
console.log("mountpoint is "+mountpoint);
selected_mountpoint = mountpoint;
get_space(selected_mountpoint);
list_files("");
//setTimeout('get_hdd_space()', 300);
//setTimeout('list_files("")', 600);
}
}
//scan_devices() - fills the device list.
function scan_devices(callback) {
makeRequest('camogm_interface.php','?cmd=listdevices',callback);
}
var devices = Array();
var selected_device = "";
var selected_mountpoint = "";
function process_scan_devices(xmldoc) {
devices = Array();
if (xmldoc.getElementsByTagName('listdevices').length > 0) {
var content = "";
content += "<table cellpadding='5' cellspacing='0' cellmargin='0'>";
content += "<tr><td></td><td><b>Partition</b></td><td><b>Mountpoint</b></td><td><b>Size</b></td><td><b>Filesystem</b></td><td></td></tr>";
for (var i=0; i < xmldoc.getElementsByTagName('item').length; i++) {
if (xmldoc.getElementsByTagName('item')[i].firstChild.firstChild.data != null) {
partition = xmldoc.getElementsByTagName('partition')[i].firstChild.data;
if (xmldoc.getElementsByTagName('item')[i].getElementsByTagName('mountpoint')[0].firstChild.data == "none") {
content += "<tr><td></td><td>"+partition+"</td><td><input id='mount_point' size='8' type='text'";
//if (partition=="/dev/hda1"){
if (partition=="/dev/sda1"){
content += " value='/var/hdd'";
}
content += "></td><td>" + xmldoc.getElementsByTagName('size')[i].firstChild.data + "</td><td>" + '</td><td><a href="#" onClick="mount_custom_partition(\''+partition+'\');">mount</a></td></tr>';
} else {
var mountpoint = xmldoc.getElementsByTagName('mountpoint')[i].firstChild.data;
content += "<tr><td><img alt=\"HDD\" src=\"images/hdd.png\"></td><td>"+partition;
content += "</td><td>"+ mountpoint+"</td><td>";
content += xmldoc.getElementsByTagName('size')[i].firstChild.data + "</td><td>" + xmldoc.getElementsByTagName('filesystem')[i].firstChild.data;
content += '</td><td><a href="#" onClick="unmount_custom_partition(\''+mountpoint+'\');">unmount</a></td></tr>';
}
devices.push(partition);
}
}
content += "</table>";
document.getElementById('ajax_devices').innerHTML = content;
}
find_selected_device();
}
function find_selected_device(){
for(var i=0;i<devices.length;i++){
if (devices[i]=="/dev/hda1") selected_device = devices[i];
if (devices[i]=="/dev/sda1") selected_device = devices[i];
break;
}
}
function create_folder() {
var name_prompt = prompt("Folder Name:");
if (name_prompt != null)
makeRequest('camogm_interface.php', '?cmd=mkdir&name=' + getCookie('current_dir') + "/" + name_prompt);
}
function process_mkdir(xmldoc) {
var sucess = xmldoc.getElementsByTagName('mkdir')[0].firstChild.data;
if (sucess == "done")
{
console.log("mkdir");
//setTimeout("list_files(getCookie('current_dir'))", 500);
}
else
alert("error creating folder");
}
function get_hdd_space() {
makeRequest('camogm_interface.php', '?cmd=get_hdd_space');
}
function get_space(mountpoint){
makeRequest('camogm_interface.php','?cmd=get_hdd_space&mountpoint='+mountpoint);
}
function process_hdd_space(xmldoc) {
var response = xmldoc.getElementsByTagName('get_hdd_space')[0].firstChild.data;
document.getElementById('hdd_rem').innerHTML = Math.round(response/1024/1024/1024*100)/100 + " GB";
//list_files("");
}
function create_webshare() {
makeRequest('camogm_interface.php','?cmd=create_symlink&mountpoint='+selected_mountpoint);
document.getElementById('create_webshare_button').style.display = "none";
//setTimeout('list_files("")', 500);
}
function set_rec_dir() {
// Show Format Tab
setCookie('tab', 2, 365);
TabbedPanels1.showPanel(2);
document.getElementById('directory').value = selected_mountpoint + getCookie('current_dir');
makeRequest('camogm_interface.php', '?cmd=set_prefix&prefix=' + selected_mountpoint + getCookie('current_dir'));
}
function list_files(dir) {
if (dir == ""){
makeRequest('camogm_interface.php', '?cmd=list_files');
setCookie("current_dir", "/", 365);
}else{
makeRequest('camogm_interface.php', '?cmd=list_files&dir=' + dir);
setCookie("current_dir", dir, 365);
}
document.getElementById('files_current_folder').innerHTML = selected_mountpoint + getCookie("current_dir");
}
function process_list_file(xmldoc) {
var can_continue = true;
if (xmldoc.getElementsByTagName('list_files').length > 0) {
if (xmldoc.getElementsByTagName('list_files')[0].firstChild!=null){
if (xmldoc.getElementsByTagName('list_files')[0].firstChild.data != null) {
if (xmldoc.getElementsByTagName('list_files')[0].firstChild.data == "no webshare found") {
console.log("webshare not found");
can_continue = false;
document.getElementById('create_webshare_button').style.display = "inline";
document.getElementById('filelist').innerHTML = "no webshare found<br>";
// ingore all odds and just create the webshare
create_webshare();
}
}
}
}
if (can_continue){
console.log("Processing file list");
var count = xmldoc.getElementsByTagName('file').length;
var response = "<table cellspacing=\"0px\" cellpadding=\"3px\" width=\"100%\">";
response += "<tr><td width=\"50%\"><b>File</b></td><td width=\"30%\"><b>Creation Date</b></td><td><b>Size</b></td></tr>";
for ( var i = 0; i < count; i++ ) {
document.getElementById('create_webshare_button').style.display = "none";
var skip = false;
if (xmldoc.getElementsByTagName('file')[i].childNodes[1].firstChild.data == "lost+found")
skip = true;
if (!skip) {
if (i%2 == 0)
response += '<tr class="file_row_even">';
else
response += '<tr class="file_row_odd">';
response += "<td>";
type = xmldoc.getElementsByTagName('file')[i].childNodes[0].firstChild.data;
filename = xmldoc.getElementsByTagName('file')[i].childNodes[1].firstChild.data;
path = xmldoc.getElementsByTagName('file')[i].childNodes[2].firstChild.data;
switch (type) {
case 'updir':
response += '<a href="#" onClick="list_files(\'' + path + '\');">';
response += '<img src="images/up_folder.gif"> ';
response += filename + "</a>";
break;
case 'dir':
response += '<a href="#" onClick="list_files(\'/' + path + '/\');">';
response += '<img src="images/folder.gif"> ';
response += filename + "</a>";
break;
case 'mov':
response += "<a href=\"http://" + location.host + "/hdd/" + path + "\">";
response += '<img src="images/quicktime.png"> ';
response += filename + "</a>";
break;
default:
response += "<a href=\"http://" + location.host + "/hdd/" + path + "\">";
response += filename + "</a>";
break;
}
response += "</td>";
response += "<td>";
var date = xmldoc.getElementsByTagName('file')[i].childNodes[4].firstChild.data;
response += date;
response += "</td>";
response += "<td>";
var size = xmldoc.getElementsByTagName('file')[i].childNodes[3].firstChild.data;
response += Math.round(size/1024/1024*100)/100 + " MB";
response += "</td>";
response += "</tr>";
}
}
response += "</table><br>";
document.getElementById('filelist').innerHTML = response;
}else{
}
}
function start_compressor(parent, port) {
makeRequest('camogm_interface.php', '?cmd=init_compressor', '&sensor_port=' + port);
parent.style.display = 'none';
}
function update_audio_form(thisform) {
with (thisform)
{
if(audio_check.checked == true) {
audio_sample_rate.disabled = false;
audio_channels.disabled = false;
audio_volume.disabled = false;
audio_syncmode.disabled = false;
document.getElementById('ajax_audio_recording').innerHTML = "<span class=\"green\">enabled</span>";
} else {
audio_sample_rate.disabled = true;
audio_channels.disabled = true;
audio_volume.disabled = true;
audio_syncmode.disabled = true;
if (audio_hardware_detected)
document.getElementById('ajax_audio_recording').innerHTML = "<span class=\"alert\">disabled</span>";
}
}
}
function makeRequest(url,parameters,callback) {
var http_request = false;
if (window.XMLHttpRequest) { // Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
http_request.overrideMimeType('text/xml');
}
} else if (window.ActiveXObject) { // IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
//http_request.onreadystatechange = process_request;
http_request.onload = function(e){
if (http_request.readyState == 4) {
if (http_request.status == 200) {
if (http_request.responseXML != null) {
process_request(http_request.responseXML)
if (typeof callback != 'undefined') {
eval(callback);
}
}
}
}
};
http_request.open('GET', url+parameters, true);
http_request.send(null);
}
function process_request(xmldoc) {
if (xmldoc.getElementsByTagName('camogm_state').length > 0) {
console.log(xmldoc.getElementsByTagName('state')[0].firstChild.data);
process_recording(xmldoc);
}
if (xmldoc.getElementsByTagName('command').length > 0) {
var command = xmldoc.getElementsByTagName('command')[0].firstChild.data;
switch (command) {
case "is_hdd_mounted":
process_is_hdd_mounted(xmldoc);
break;
case "list_files":
process_list_file(xmldoc);
break;
case "file_rename":
process_rename_file(xmldoc);
break;
case "get_hdd_space":
process_hdd_space(xmldoc);
break;
case "mount":
process_mount_hdd(xmldoc);
break;
case "mkdir":
process_mkdir(xmldoc);
break;
case "check_audio_hardware":
process_check_audio_hardware(xmldoc);
break;
case "listdevices":
process_scan_devices(xmldoc);
break;
default:
break;
}
}
}
function process_recording(xmldoc) {
var file_duration = xmldoc.getElementsByTagName('file_duration')[0].firstChild.data;
var state = xmldoc.getElementsByTagName('state')[0].firstChild.data;
var frame_number = xmldoc.getElementsByTagName('frame_number')[0].firstChild.data;
var file_length = xmldoc.getElementsByTagName('file_length')[0].firstChild.data;
var file_name = xmldoc.getElementsByTagName('file_name')[0].firstChild.data;
if (state=='"stopped"'){
clearInterval(update_intvl);
}
//Update HTML
document.getElementById('ajax_state').innerHTML = state.substring(1, state.length-1);
document.getElementById('ajax_file_duration').innerHTML = Math.round(file_duration*100)/100 + " seconds / " + frame_number + " frames";
document.getElementById('ajax_file_length').innerHTML = Math.round(file_length/1024/1024*100)/100 + " MB";
document.getElementById('ajax_data_rate').innerHTML = Math.round(file_length/1024/1024/file_duration*800)/100 + " Mbit/s | " + Math.round(file_length/1024/1024*100/file_duration)/100 + " MByte/s";
document.getElementById('ajax_data_rate2').innerHTML = Math.round(file_length/1024/1024/frame_number*800)/100 + " Mbit/frame | " + Math.round(file_length/1024/1024/frame_number*100)/100 + " MByte/frame";
//document.getElementById('ajax_fps').innerHTML = Math.round(frame_number/file_duration*100)/100 + " fps";
document.getElementById('ajax_file_name').innerHTML = file_name.substring(1, file_name.length-1);
//Update Buffer Bar
var buffer_free = xmldoc.getElementsByTagName('buffer_free')[0].firstChild.data;
var buffer_used = xmldoc.getElementsByTagName('buffer_used')[0].firstChild.data;
//var buffer_rp = xmldoc.getElementsByTagName('circbuf_rp')[0].firstChild.data; // buffer read pointer
//var buffer_filled = buffer_used - buffer_rp;
document.getElementById('buffer_free').style.width = Math.round(buffer_free / 19791872 * 300);
document.getElementById('buffer_used').style.width = Math.round(buffer_used / 19791872 * 300);
//get_hdd_space();
get_space(selected_mountpoint);
if (xmldoc.getElementsByTagName('buffer_overruns')[0].firstChild.data > 0)
alert ("Buffer overrun! current datarate exceeds max. write rate")
}
recording = false;
function update_state() {
//if (recording) {
makeRequest('camogm_interface.php','?cmd=status');
//setTimeout('update_state()', 200);
//}
}
var update_intvl;
function toggle_recording() {
if (recording) // Stop it
{
recording = false;
makeRequest('camogm_interface.php', '?cmd=stop');
//show it
document.getElementById('sitecoloumn').style.backgroundColor = "#F4F4F2";
document.getElementById('record_text').innerHTML = "<img src=\"images/record.gif\" style=\"position:relative; bottom:-5px;\"> RECORD";
// rename file from user prompt
if (document.filenames.file_name_scheme[1].checked) {
var name_prompt = prompt("Rename recorded file to: ");
if (name_prompt != null)
rename_file(document.getElementById('ajax_file_name').innerHTML, name_prompt);
//alert(document.getElementById('ajax_file_name').innerHTML);
}
// rename file from advanced naming scheme
if (document.filenames.file_name_scheme[2].checked)
{
rename_file(document.getElementById('ajax_file_name').innerHTML, document.getElementById('directory').value + document.filenames.result.value);
}
//setTimeout('list_files(getCookie("current_dir"))', 300);
//setTimeout('get_hdd_space()', 600);
//setTimeout(last_update, 900);
//get_space(selected_mountpoint);
}
else // Start it
{
// Show Status Tab
setCookie('tab', 0, 365);
TabbedPanels1.showPanel(0);
recording = true;
makeRequest('camogm_interface.php', '?cmd=start');
// show we are recording
document.getElementById('record_text').innerHTML = "<img src=\"images/stop.gif\" style=\"position:relative; bottom:-5px;\"> STOP";
document.getElementById('sitecoloumn').style.backgroundColor = "#AF2020";
clearInterval(update_intvl);
update_intvl = setInterval(update_state,1000);
}
//update_state();
}
function rename_file(oldname, newname) {
makeRequest('camogm_interface.php', '?cmd=file_rename&file_old=' + oldname + '&file_new=' + newname);
}
function process_rename_file(xmldoc) {
var response = xmldoc.getElementsByTagName('file_rename')[0].firstChild.data;
if (response != "done")
alert ("renaming failed: " + response);
//setTimeout('list_files(getCookie("current_dir"))', 300);
}
function update_fps_reduce(parent) {
if (document.getElementById('fps_reduce_frameskip').checked) {
document.getElementById('timelapse_id').disabled = true;
document.getElementById('frameskip_id').disabled = false;
}
if (document.getElementById('fps_reduce_timelapse').checked) {
document.getElementById('timelapse_id').disabled = false;
document.getElementById('frameskip_id').disabled = true;
}
}
function update_live_image() {
var imgsrv_port = 2323;
var radios = document.getElementsByName("selected_sensor_port");
for (var i = 0; i < radios.length; i++) {
if (radios[i].checked) {
imgsrv_port = imgsrv_port + i;
break;
}
}
document.getElementById('live-picture').src = "http://" + location.host + ":" + imgsrv_port + "/bimg?" + Math.random()*99999999999;
}
function size_up_image() {
document.getElementById('live-picture').width += 40;
document.getElementById('live-picture').height += 30;
var old_height = document.getElementById('CollapsiblePanel1Inhalt').style.height;
document.getElementById('CollapsiblePanel1Inhalt').style.height = parseInt(old_height.substring(0, old_height.length-2)) + 30; + "px";
}
function size_down_image() {
document.getElementById('live-picture').width -= 40;
document.getElementById('live-picture').height -= 30;
var old_height = document.getElementById('CollapsiblePanel1Inhalt').style.height;
document.getElementById('CollapsiblePanel1Inhalt').style.height = parseInt(old_height.substring(0, old_height.length-2)) - 30; + "px";
}
function help(caller) {
switch (caller) {
case 'sensor':
alert("The sensor is not yet in a working state. It needs to be initated first. Tools like camvc should automatically do this for you.");
break;
case 'debug':
alert("The higher the debug-level the more information is written to the debug file (it may slow down camogm and cause it to drop frames even if it could handle it with no/lower debug-level output).")
break;
}
}
function format_changed(parent) {
//alert(parent.value); // debug
if (parent.value == "jpg")
{
document.filenames.file_name_scheme[1].disabled = true;
document.filenames.file_name_scheme[0].checked = true;
document.getElementById('filename_prompt_text').style.color = "#777777";
}
else
{
document.filenames.file_name_scheme[1].disabled = false;
document.getElementById('filename_prompt_text').style.color = "#000";
}
update_name_scheme();
}
function filenamesel_changed() {
if (document.filenames.file_name_scheme[2].checked)
document.getElementById('advanced_name_panel').style.display = "block";
else
{
document.getElementById('advanced_name_panel').style.display = "none";
}
var result = "";
for (var i = 0; i < document.filenames.file_name_scheme.length; i++) {
if (document.filenames.file_name_scheme[i].checked)
result = document.filenames.file_name_scheme[i].value;
}
setCookie('file_name_scheme', result, 365);
}
function update_name_scheme() {
if (document.filenames.prefix_enable.checked)
document.filenames.pre_name.disabled = false;
else
document.filenames.pre_name.disabled = true;
// save all form data so it survives a page reload
setCookie('filenames_prefix_disabled', document.filenames.pre_name.disabled, 365);
setCookie('filenames_prefix', document.filenames.pre_name.value, 365);
if (document.filenames.scene_enable.checked)
document.filenames.scene.disabled = false;
else
document.filenames.scene.disabled = true;
setCookie('filenames_scene_disabled', document.filenames.scene_enable.disabled, 365);
setCookie('filenames_scene', document.filenames.scene.value, 365);
if (document.filenames.shot_enable.checked)
document.filenames.shot.disabled = false;
else
document.filenames.shot.disabled = true;
setCookie('filenames_shot_disabled', document.filenames.shot.disabled, 365);
setCookie('filenames_shot', document.filenames.shot.value, 365);
if (document.filenames.take_enable.checked)
document.filenames.take.disabled = false;
else
document.filenames.take.disabled = true;
setCookie('filenames_take_disabled', document.filenames.take.disabled, 365);
setCookie('filenames_take', document.filenames.take.value, 365);
if (document.filenames.custom_enable.checked)
{
document.filenames.custom.disabled = false;
document.filenames.custom_number.disabled = false;
}
else
{
document.filenames.custom.disabled = true;
document.filenames.custom_number.disabled = true;
}
setCookie('filenames_custom_disabled', document.filenames.custom.disabled, 365);
setCookie('filenames_custom', document.filenames.custom.value, 365);
setCookie('filenames_customnumber', document.filenames.custom_number.value, 365);
// Result
if (document.filenames.prefix_enable.checked)
prefix = document.filenames.pre_name.value;
else
prefix = "";
if (document.filenames.scene_enable.checked && document.filenames.scene.value != "")
scene = "_Scene" + document.filenames.scene.value;
else
scene = "";
if (document.filenames.shot_enable.checked && document.filenames.shot.value != "")
shot = "_Shot" + document.filenames.shot.value;
else
shot = "";
if (document.filenames.take_enable.checked && document.filenames.take.value != "")
take = "_Take" + document.filenames.take.value;
else
take = "";
if (document.filenames.custom_enable.checked)
custom = "_" + document.filenames.custom.value + document.filenames.custom_number.value;
else
custom = "";
var extension = "";
for (var i = 0; i < document.format.container.length; i++) {
if (document.format.container[i].checked)
extension = document.format.container[i].value;
}
document.filenames.result.value = prefix + scene + shot + take + custom + "." + extension;
}
function raise(target) {
document.getElementById(target).value++;
update_name_scheme();
}
function lower(target) {
if (document.getElementById(target).value != 0)
document.getElementById(target).value--;
update_name_scheme();
}
function live_image_auto_update_changed() {
if (document.getElementById('live_image_auto_update').checked == true) {
validate_update_freq();
update_live_image_loop();
}
}
function validate_update_freq() {
if (document.getElementById('live_image_auto_update_frequency').value > 60)
document.getElementById('live_image_auto_update_frequency').value = 60;
if (document.getElementById('live_image_auto_update_frequency').value < 1)
document.getElementById('live_image_auto_update_frequency').value = 1;
}
function update_live_image_loop() {
if (document.getElementById('live_image_auto_update').checked == true) {
update_live_image();
setTimeout('update_live_image_loop()', document.getElementById('live_image_auto_update_frequency').value*1000);
}
}
function setCookie(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name + "=" + escape(value) + ((expiredays==null) ? "" : ";expires="+exdate.toGMTString());
}
function getCookie(c_name) {
if (document.cookie.length>0) {
c_start = document.cookie.indexOf(c_name + "=");
if (c_start != -1) {
c_start = c_start + c_name.length + 1;
c_end = document.cookie.indexOf(";", c_start);
if (c_end == -1)
c_end = document.cookie.length;
return unescape(document.cookie.substring(c_start, c_end));
}
}
return "";
}
function check_audio_hardware() {
makeRequest('camogm_interface.php', '?cmd=check_audio_hardware');
}
audio_hardware_detected = false;
function process_check_audio_hardware(xmldoc) {
var response = xmldoc.getElementsByTagName('check_audio_hardware')[0].firstChild.data;
if (response == "no Audio Hardware detected")
{
audio_hardware_detected = false;
document.getElementById('ajax_detected_audio_hardware').innerHTML = "<span style='color:red;'>" + response + "</span>";
document.getElementById('audio_sample_rate').disabled = true;
document.getElementById('audio_check').disabled = true;
document.getElementById('audio_channels').disabled = true;
document.getElementById('audio_check').checked = false;
document.getElementById('audio_volume').checked = false;
document.getElementById('audio_syncmode').checked = false;
document.getElementById('ajax_audio_recording').innerHTML = "disabled";
}
else
{
audio_hardware_detected = true;
document.getElementById('ajax_detected_audio_hardware').innerHTML = "<span style='color:green;'>" + response + "</span>";
document.getElementById('audio_check').disabled = false;
}
setTimeout('update_audio_form(document.getElementById("audioform"))', 300);
}
function test_audio_playback(soundfile) {
makeRequest('camogm_interface.php', '?cmd=test_audio_playback&soundfile=' + soundfile);
}
function calc_split_size() {
if (document.getElementById('split_size_input').value > 1000000000)
var result = Math.round(document.getElementById('split_size_input').value/1024/1024/1024*100)/100 + " GB";
else
var result = Math.round(document.getElementById('split_size_input').value/1024/1024*100)/100 + " MB";
//alert(result);
document.getElementById('split_size_calculation').innerHTML = " = " + result;
}
function toggle_buffer() {
if (document.getElementById('buffer_bar').style.display == "none") {
document.getElementById('buffer_bar').style.display = "inline";
document.getElementById('buffer_toggle_link').style.display = "none";
}
else {
document.getElementById('buffer_bar').style.display = "none";
document.getElementById('buffer_toggle_link').style.display = "block";
}
}
// enable fast recording through disk driver
function fast_rec_changed(parent)
{
if (parent.checked) {
document.getElementById('radioJpg').checked = true;
document.getElementById('directory').disabled = true;
} else {
document.getElementById('directory').disabled = false;
}
}
<?php
/*!***************************************************************************
*! FILE NAME : camogmgui.php
*! DESCRIPTION: GUI for the camogm recorder
*! Copyright (C) 2008 Elphel, Inc
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: camogmgui.php,v $
*! Revision 1.13 2009/10/18 14:54:50 oneartplease
*! made buffer bar toggleable
*! and off by default
*!
*! Revision 1.11 2009/10/10 21:32:49 elphel
*! Added "save_gp=1" so the free/used buffer indicator is correct
*!
*! Revision 1.10 2009/10/02 19:21:10 oneartplease
*! button layout overflow fixed
*!
*! Revision 1.9 2009/06/24 13:41:33 oneartplease
*! Split size now shows human well readable value next to input field
*!
*! Revision 1.4 2009/03/26 12:20:40 oneartplease
*! audio and geotagging updates, both are not fully working yet though
*!
*! Revision 1.8 2009/01/14 08:26:19 oneartplease
*! minor updates
*!
*!
*! Revision 1."" 2008/07/30 Sebastian Pichelhofer
*! some stability improvements
*!
*! Revision 1.1 2008/07/25 Sebastian Pichelhofer
*! added custom commands form and color tags for better overview of current development status
*!
*! Revision 1.0 2008/07/08 Sebastian Pichelhofer
*! initial revision with basic interface
*!
*/
$reload = false;
$pipe = "/var/state/camogm.state";
$cmd_pipe = "/var/state/camogm_cmd";
$cmd_port = "3456";
$start_str = "camogm -n " . $cmd_pipe . " -p " . $cmd_port;
$mode = 0777;
$sensor_ports = elphel_num_sensors();
$default_imgsrv_port = 2323;
// check if any compressor is in running state
function check_compressors($states)
{
global $sensor_ports;
$ret_val = 0;
for ($i = 0; $i < $sensor_ports; $i++) {
if ($states[$i] == "running")
$ret_val = 1;
}
return $ret_val;
}
if(!file_exists($pipe)) {
// create the pipe
umask(0);
if(!posix_mkfifo($pipe,$mode))
echo "Error creating pipe!";
} else {
unlink($pipe);
umask(0);
if(!posix_mkfifo($pipe,$mode))
echo "Error creating pipe!";
}
// is camogm running
$camogm_running = false;
exec('ps | grep "camogm"', $arr);
function low_daemon($v)
{
return (substr($v, -1) != ']');
}
$p = (array_filter($arr, "low_daemon"));
$check = implode("<br />",$p);
if (strstr($check, $start_str))
$camogm_running = true;
else
$camogm_running = false;
// if camogm is not running start it
if (!$camogm_running)
{
header("Refresh: 2; url=".$_SERVER['PHP_SELF']);
echo "<html><head>";
echo "<script language=\"JavaScript\" src=\"camogmgui.js\"></script>";
echo "</head><body onLoad=\"reload();\">";
echo "<h1>starting camogm</h1><br />page will reload automatically in a few moments<br /></body></html>";
exit;
}
if ($camogm_running) {
$fcmd = fopen($cmd_pipe, "w");
}
// format tab submit
if (isset($_POST['settings_format'])){
switch($_POST['container']){
case'ogm':
$container = $_POST['container'];
break;
case'jpg':
$container = $_POST['container'];
break;
case'mov':
$container = $_POST['container'];
break;
default:
$container = "mov";
break;
}
if ($camogm_running) {
// set format
fprintf($fcmd, "format=%s;\n", $container);
// set record directory
$prefix = $_POST['prefix'];
fprintf($fcmd, "prefix=%s;\n", $prefix);
setcookie("directory", $prefix); // save as cookie so we can get prefered record directory even after camera reboot
//set debug file
$debug = $_POST['debug'];
$debug_file = $_POST['debugfile'];
$debug_level = $_POST['debuglevel'];
if ($debug == "yes")
{
fprintf($fcmd, "debug=%s;\ndebuglev=%s;\n", $debug_file, $debug_level);
}
else
fprintf($fcmd, "debug;\ndebuglev=1;\n");
}
}
// advanced tab submit
if (isset($_POST['advanced_settings'])) {
if ($camogm_running) {
// we can only either skip frames or seconds
if ($_POST['fps_reduce'] == "frameskip")
fprintf($fcmd, "frameskip=%s;\n", $_POST['frameskip']);
else
fprintf($fcmd, "timelapse=%s;\n", $_POST['timelapse']);
fprintf($fcmd, "timescale=%s;\n", $_POST['timescale']);
if ($_POST['exif'] == "yes")
fprintf($fcmd, "exif=1;\n");
else
fprintf($fcmd, "exif=0;\n");
if (isset($_POST['split_size']))
fprintf($fcmd, "length=".$_POST['split_size'].";\n");
if (isset($_POST['split_length']))
fprintf($fcmd, "duration=".$_POST['split_length'].";\n");
}
}
// Audio tab submit
if (isset($_POST['settings_sound'])) {
if ($camogm_running) {
if ($_POST['audio_check'] == "on")
fprintf($fcmd, "audio=on;\n");
else
fprintf($fcmd, "audio=off;\n");
fprintf($fcmd, "audio_format=%s/%s;\n", $_POST['audio_sample_rate'], $_POST['audio_channels']);
// TODO: set volume here!
if ($_POST['audio_syncmode'] == "normal")
fprintf($fcmd, "allow_sync=disable;\n");
else
fprintf($fcmd, "allow_sync=enable;\n");
}
}
// Geo-Tagging tab submit
if (isset($_POST['settings_geotagging'])) {
if ($camogm_running) {
if ($_POST['geotag_enable'] == "on")
fprintf($fcmd, "kml=1;\n");
else
fprintf($fcmd, "kml=0;\n");
fprintf($fcmd, "kml_period=".$_POST['geotag_period'].";\n");
fprintf($fcmd, "kml_hhf=".$_POST['geotag_hFov']/2 .";\n");
fprintf($fcmd, "kml_vhf=".$_POST['geotag_vFov']/2 .";\n");
if($_POST['geotag_altmode'] == "absolute")
fprintf($fcmd, "kml_alt=gps;\n");
else
fprintf($fcmd, "kml_alt=ground;\n");
}
}
// Get XML data for init
if ($camogm_running) {
fprintf($fcmd, "xstatus=%s;\n", $pipe);
fclose($fcmd);
$xml_status = file_get_contents($pipe);
require_once('xml_simple.php');
function parse_array($element)
{
global $logdata, $logindex;
foreach ($element as $header => $value)
{
if (is_array($value))
{
parse_array($value);
$logindex++;
} else
{
$logdata[$logindex][$header] = $value;
}
}
}
$parser =& new xml_simple('UTF-8');
$request = $parser->parse($xml_status);
// catch errors
$error_code = 0;
if (!$request) {
$error_code = 1;
echo("XML error: ".$parser->error);
}
$logdata = array();
$logindex = 0;
parse_array($parser->tree);
// Load data from XML
$xml_format = substr($logdata[0]['format'], 1, strlen($logdata[0]['format'])-2);
$xml_state = substr($logdata[0]['state'], 1, strlen($logdata[0]['state'])-2);
$xml_directory = substr($logdata[0]['prefix'], 1, strlen($logdata[0]['prefix'])-2);
$xml_file_length = substr($logdata[0]['file_length'], 0, strlen($logdata[0]['file_length'])); // file size in bytes
$xml_file_duration = substr($logdata[0]['file_duration'], 0, strlen($logdata[0]['file_duration']));
$xml_frame_number = substr($logdata[0]['frame_number'], 0, strlen($logdata[0]['frame_number']));
$xml_res_x = substr($logdata[0]['frame_width'], 0, strlen($logdata[0]['frame_width']));
$xml_res_y = substr($logdata[0]['frame_height'], 0, strlen($logdata[0]['frame_height']));
// Advanced Settings
$xml_timescale = substr($logdata[0]['timescale'], 0, strlen($logdata[0]['timescale']));
$xml_frameskip = substr($logdata[0]['frames_skip'], 0, strlen($logdata[0]['frames_skip']));
$xml_timelapse = substr($logdata[0]['seconds_skip'], 0, strlen($logdata[0]['seconds_skip']));
$xml_exif = substr($logdata[0]['exif'], 0, strlen($logdata[0]['exif']));
$xml_split_size = substr($logdata[0]['max_length'], 0, strlen($logdata[0]['max_length']));
$xml_split_length = substr($logdata[0]['max_duration'], 0, strlen($logdata[0]['max_duration']));
$xml_debug_file = substr($logdata[0]['debug_output'], 1, strlen($logdata[0]['debug_output'])-2);
$xml_debug_level = substr($logdata[0]['debug_level'], 0, strlen($logdata[0]['debug_level']));
if (($xml_debug_file == "") || ($xml_debug_file == "null") || ($xml_debug_file == "none") || ($xml_debug_file == " /dev/null"))
$xml_debug = false;
else
$xml_debug = true;
// Geo-Tagging
$xml_geotagging_enabled = substr($logdata[0]['kml_enable'], 1, strlen($logdata[0]['kml_enable'])-2);
$xml_geotagging_hFOV = substr($logdata[0]['kml_horHalfFov'], 1, strlen($logdata[0]['kml_horHalfFov'])-2);
$xml_geotagging_vFOV = substr($logdata[0]['kml_vertHalfFov'], 1, strlen($logdata[0]['kml_vertHalfFov'])-2);
$xml_geotagging_near = substr($logdata[0]['kml_near'], 1, strlen($logdata[0]['kml_near'])-2);
$xml_geotagging_heightmode = substr($logdata[0]['kml_height_mode'], 1, strlen($logdata[0]['kml_height_mode'])-2);
$xml_geotagging_height = substr($logdata[0]['kml_height'], 1, strlen($logdata[0]['kml_height'])-2);
$xml_geotagging_period = substr($logdata[0]['kml_period'], 0, strlen($logdata[0]['kml_period']));
// Audio Recording
$xml_audiorecording_enabled = substr($logdata[0]['audio_enable'], 1, strlen($logdata[0]['audio_enable'])-2);
$xml_audio_channels = substr($logdata[0]['audio_channels'], 1, strlen($logdata[0]['audio_channels'])-2);
$xml_audio_rate = substr($logdata[0]['audio_rate'], 1, strlen($logdata[0]['audio_rate'])-2);
$xml_audio_volume = substr($logdata[0]['audio_volume'], 1, strlen($logdata[0]['audio_volume'])-2);
$xml_audio_syncmode = substr($logdata[0]['allow_sync'], 1, strlen($logdata[0]['allow_sync'])-2);
// Get per sensor port parameters
$xml_compressor_state = array();
for ($i = 0; $i < $sensor_ports; $i++) {
$xml_compressor_state[$i] = substr($logdata[$i]['compressor_state'], 1, strlen($logdata[$i]['compressor_state'])-2);
}
if ($camogm_running) {
if (($xml_directory == "\"\"") || ($xml_directory == ""))
{
$fcmd = fopen($cmd_pipe, "w");
if (isset($_COOKIE['directory'])) // load directory cookie if nothing has been set
{
$xml_directory = $_COOKIE['directory'];
fprintf($fcmd, "prefix=%s;\n", $xml_directory);
}
else
fprintf($fcmd, "prefix=%s;\n", "/var/hdd/");
}
}
if ($xml_format == "'none'") // use quicktime mov as default if no container format has been selected
fprintf($fcmd, "format=mov;");
}
// GUI
?>
<html>
<head>
<title>HDD / CF Recorder</title>
<link href="camogmgui.css" rel="stylesheet" type="text/css" media="screen">
<link href="SpryTabbedPanels.css" rel="stylesheet" type="text/css">
<link href="SpryCollapsiblePanel.css" rel="stylesheet" type="text/css">
<script src="camogmgui.js" type="text/javascript"></script>
<script src="SpryTabbedPanels.js" type="text/javascript"></script>
<script src="SpryCollapsiblePanel.js" type="text/javascript"></script>
</head>
<body onLoad="init();">
<div id="sitecoloumn">
<div id="live-image">
<div id="CollapsiblePanel1" class="CollapsiblePanel">
<div class="CollapsiblePanelTab" tabindex="0">Live-Preview</div>
<div id="CollapsiblePanel1Inhalt" class="CollapsiblePanelContent">
<div id="live-image-header">
<table border="0" cellpadding="2" cellspacing="0">
<tr>
<td width="245px"></td>
<td width="100px"><a href="#" onClick="update_live_image();">Update</a></td>
<td width="100px">Size: <a href="#" onClick="size_up_image()">+</a> | <a href="#" onClick="size_down_image()">-</a></td>
<td width="200px">
<div class="sensor_ports">
<input id="live_image_auto_update" type="checkbox" onChange="live_image_auto_update_changed();" name="live_image_auto_update"> Auto Update every:
<input id="live_image_auto_update_frequency" type="text" name="live_image_auto_update_frequency" value="5.0" size="3" onChange="validate_update_freq();"> seconds
</div>
</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
if ($i == 0)
echo "<td>" . "<div class=\"sensor_ports\">" . "<input type=\"radio\" name=\"selected_sensor_port\" value=\"$i\" checked=\"true\" onchange=\"update_live_image();\">" .
"Port " . $i . "</div>" . "</td>";
else
echo "<td>" . "<div class=\"sensor_ports\">" . "<input type=\"radio\" name=\"selected_sensor_port\" value=\"$i\" onchange=\"update_live_image();\">" .
"Port " . $i . "</div>" . "</td>";
}
?>
</tr>
</table>
</div>
<img id="live-picture" style="border:solid 1px #000; margin:3px;" src="http://<? echo $_SERVER['SERVER_NAME'] . ":" . $default_imgsrv_port; ?>/bimg" width="400" height="300"><br />
</div>
</div>
</div>
<div id="header">HDD / CF Recorder</div>
<div id="buffer_toggle"><a id="buffer_toggle_link" onclick="toggle_buffer();" href="#">Show Buffer</a></div>
<div id="buffer_bar" onclick="toggle_buffer();" style="display:none;">Buffer: <span id="buffer_free">free</span><span id="buffer_used">used</span></div>
<div id="help_link"><a target="_blank" href="http://wiki.elphel.com/index.php?title=Camogmgui">HELP</a></div>
<table border="0" cellpadding="2" cellspacing="5">
<tr><td>
<div id="files">
<div id="files_header">
Device: <span id="mounted_devices">loading ...</span><br />
<div id="file_browser_commands">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td width="70"><a href="#" id="refresh_file_list" title="refresh the filebrowser" onClick='list_files(getCookie("current_dir")); get_hdd_space();'><img src="images/reload.png" style="bottom:-2px; position:relative;"> Reload</a></td>
<td width="105"><a href="#" id="mount_hdd_button" onClick="mount_hdd();"> Mount</a>
<a href="#" id="create_folder" onClick="create_folder();"><img src="images/create_folder.png" title="create a new folder in the currently open directory below" style="bottom:-3px; position:relative;"> Create Folder</a></td>
<td width="125"><a href="#" id="create_webshare_button" onClick="create_webshare();"> Create Webshare</a>
<a href="#" id="set_rec_dir" onClick="set_rec_dir();" title="set the currently open directory below as the target folder for recording video files"><img src="images/rec_folder.png" style="bottom:-3px; position:relative;"> Set Target Folder</a></td>
</tr>
</table>
</div>
</div>
<span id="filelist">nothing mounted.</span><br />
<div id="files_footer">Remaining Free Space: <span id="hdd_rem">loading ...</span><span id="files_current_folder">loading...</span></div>
</div>
</td>
<td valign="top">
<div id="record" >
<a href="#" onClick="toggle_recording();"><span id="record_text"><img src="images/record.gif" style="position:relative; bottom:-5px;"> RECORD</span></a> </div>
<br /><br /><br />
<div id="TabbedPanels1" class="TabbedPanels">
<ul class="TabbedPanelsTabGroup">
<?
if ((check_compressors($xml_compressor_state) != 1) || (!$camogm_running))
echo "<li class=\"TabbedPanelsTabAlert\" tabindex=\"0\">Status</li>";
else
echo "<li class=\"TabbedPanelsTab\" tabindex=\"0\">Status</li>";
?>
<li class="TabbedPanelsTab" tabindex="1">Filenames</li>
<li class="TabbedPanelsTab" tabindex="2">Format</li>
<li class="TabbedPanelsTab" tabindex="3">Audio</li>
<li class="TabbedPanelsTab" tabindex="4">Geo-Tagging</li>
<li class="TabbedPanelsTab" tabindex="5">Advanced</li>
</ul>
<div class="TabbedPanelsContentGroup">
<div class="TabbedPanelsContent">
<!-- Status -->
<table class="state_table" border="0px" cellpadding="opx" cellspacing="0px">
<!-- Table header -->
<tr><td width="120px"></td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td>Port " . $i . "</td>";
}
?>
</tr>
<!-- Sensor port status -->
<tr><td>Sensor</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td>";
if (elphel_get_state($i) == 0)
{
echo "<span class=\"alert\">not initialized!</span>";
echo " <a href=\"#\" onClick=\"help('sensor');\"><img src=\"images/help.png\"></a>";
}
else
echo "<span class=\"green\"> working</span>";
echo "</td>";
}
?>
</tr>
<!-- Compressor status -->
<tr><td>Compressor</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td>";
if ($xml_compressor_state[$i] != "running") {
echo "<span class=\"alert\">not running!</span>";
echo " <a href=\"#\" OnClick=\"start_compressor(this, $i); window.location.reload();\">start compressor</a>";
}
else
echo "<span class=\"green\"> running</span>";
echo "</td>";
}
?>
</tr>
<!-- Image resolution on each port -->
<tr><td>Image resolution</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td id=\"ajax_res\">";
echo elphel_get_P_value($i, ELPHEL_ACTUAL_WIDTH) . " x " . elphel_get_P_value($i, ELPHEL_ACTUAL_HEIGHT);
echo "</td>";
}
?>
</tr>
<!-- JPEG quality on each port -->
<tr><td>JPEG quality</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td id=\"ajax_qual\">";
echo elphel_get_P_value($i, ELPHEL_QUALITY) . " %";
echo "</td>";
}
?>
</tr>
<!-- Frame rate on each port -->
<tr><td>Framerate</td>
<?php
for ($i = 0; $i < $sensor_ports; $i++) {
echo "<td id=\"ajax_fps\">";
echo elphel_get_P_value($i, ELPHEL_FP1000S) / 1000 . " fps";
echo "</td>";
}
?>
</tr>
</table>
<br />
<br />
<table class="state_table" border="0px" cellpadding="0px" cellspacing="0px">
<tr><td width="120px">Camogm:</td>
<td>
<?php
if (!$camogm_running) {
echo "<span class=\"alert\">NOT running!</span>";
echo " <input name=\"camogm_start\" type=\"button\" value=\"start camogm\" >";
}
else
echo "<span class=\"green\"> running</span>";
?>
</td>
</tr>
<tr><td>Recording:</td><td id="ajax_state"><? echo $xml_state; ?></td></tr>
<tr><td>Audio Recording:</td><td id="ajax_audio_recording">loading...</td></tr>
<tr><td>Geo-Tagging:</td><td id="ajax_geotag_enabled"><? if($xml_geotagging_enabled == "yes") echo "enabled"; else echo "disabled"; ?></td></tr>
<tr><td>Filename:</td><td id="ajax_file_name">-</td></tr>
<tr><td>Record Time:</td><td id="ajax_file_duration">-</td></tr>
<tr><td>File Size:</td><td id="ajax_file_length">-</td></tr>
<tr><td>Data Rate:</td><td id="ajax_data_rate">-</td></tr>
<tr><td>Data Rate:</td><td id="ajax_data_rate2">-</td></tr>
</table>
</div>
<div class="TabbedPanelsContent">
<!-- File-Names -->
<form method="POST" name="filenames">
<b>File-Names:</b><br />
<?
if(isset($_COOKIE['file_name_scheme']))
$file_naming_scheme = $_COOKIE['file_name_scheme'];
else
$file_naming_scheme = "default";
if ($file_naming_scheme == "default")
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"default\" checked> Default (Unix-Timestamp)<br />";
else
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"default\"> Default (Unix-Timestamp)<br />";
if ($file_naming_scheme == "prompt")
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"prompt\" checked> <span id=\"filename_prompt_text\">Prompt for filename after recording</span><br />";
else
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"prompt\"> <span id=\"filename_prompt_text\">Prompt for filename after recording</span><br />";
if ($file_naming_scheme == "advanced")
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"advanced\" checked> Advanced Naming-Schemes<br />";
else
echo "<input type=\"radio\" style=\"top:3px; position:relative;\" name=\"file_name_scheme\" onChange=\"filenamesel_changed();\" value=\"advanced\"> Advanced Naming-Schemes<br />";
?>
<br />
<?
if ($file_naming_scheme == "advanced")
echo "<div id=\"advanced_name_panel\" style=\"display:block;\">";
else
echo "<div id=\"advanced_name_panel\" style=\"display:none;\">";
?>
<table width="100%">
<tr><td><input type="checkbox" onChange="update_name_scheme();" name="prefix_enable" <? if (isset($_COOKIE['filenames_prefix_disabled'])) if ($_COOKIE['filenames_prefix_disabled'] == "false") echo "checked"; ?>> Prefix:</td><td><input name="pre_name" onKeyUp="update_name_scheme();" onChange="update_name_scheme();" type="text" value="<? if (isset($_COOKIE['filenames_prefix'])) echo $_COOKIE['filenames_prefix']; ?>"></td></tr>
<tr><td><input type="checkbox" onChange="update_name_scheme();" name="scene_enable" <? if (isset($_COOKIE['filenames_scene_disabled'])) if ($_COOKIE['filenames_prefix_disabled'] == "false") echo "checked"; ?>> Scene:</td><td><input id="scene" name="scene" onKeyUp="update_name_scheme();" onChange="update_name_scheme();" type="text" value="<? if (isset($_COOKIE['filenames_scene'])) echo $_COOKIE['filenames_scene']; ?>"><input type="button" value="+" onClick="raise('scene');"><input type="button" onClick="lower('scene');" value="-"></td></tr>
<tr><td><input type="checkbox" onChange="update_name_scheme();" name="shot_enable" <? if (isset($_COOKIE['filenames_shot_disabled'])) if ($_COOKIE['filenames_shot_disabled'] == "false") echo "checked"; ?>> Shot:</td><td><input id="shot" name="shot" onKeyUp="update_name_scheme();" onChange="update_name_scheme();" type="text" value="<? if (isset($_COOKIE['filenames_shot'])) echo $_COOKIE['filenames_shot']; ?>"><input type="button" value="+" onClick="raise('shot');"><input type="button" onClick="lower('shot');" value="-"></td></tr>
<tr><td><input type="checkbox" onChange="update_name_scheme();" name="take_enable" <? if (isset($_COOKIE['filenames_take_disabled'])) if ($_COOKIE['filenames_take_disabled'] == "false") echo "checked"; ?>> Take:</td><td><input id="take" name="take" onKeyUp="update_name_scheme();" onChange="update_name_scheme();" type="text" value="<? if (isset($_COOKIE['filenames_take'])) echo $_COOKIE['filenames_take']; ?>"><input type="button" value="+" onClick="raise('take');"><input type="button" value="-" onClick="lower('take');"></td></tr>
<tr><td><input type="checkbox" onChange="update_name_scheme();" name="custom_enable" <? if (isset($_COOKIE['filenames_custom_disabled'])) if ($_COOKIE['filenames_custom_disabled'] == "false") echo "checked"; ?>> Custom:</td><td><input name="custom" onKeyUp="update_name_scheme();" onChange="update_name_scheme();" type="text" value="<? if (isset($_COOKIE['filenames_custom'])) echo $_COOKIE['filenames_custom']; ?>"> <input id="custom_number" name="custom_number" onKeyUp="update_name_scheme();" type="text" size="4" value="<? if (isset($_COOKIE['filenames_customnumber'])) echo $_COOKIE['filenames_customnumber']; ?>"><input type="button" value="+" onClick="raise('custom_number');"><input type="button" value="-" onClick="lower('custom_number');"></td></tr>
<tr><td>Result:</td><td><input readonly name="result" size="40" type="text"></td></tr>
</table>
</div>
</form>
</div>
<div class="TabbedPanelsContent">
<!-- Format -->
<form method="POST" name="format">
<b>Format:</b><br />
<?
if ($xml_format == "ogm")
echo "<input type=\"radio\" id=\"radioOgm\" style=\"top:3px; position:relative;\" name=\"container\" value=\"ogm\" onChange=\"format_changed(this);\" checked> Ogg Media Stream<br />";
else
echo "<input type=\"radio\" id=\"radioOgm\" style=\"top:3px; position:relative;\" name=\"container\" value=\"ogm\" onChange=\"format_changed(this);\"> Ogg Media Stream<br />";
if ($xml_format == "mov")
echo "<input type=\"radio\" id=\"radioMov\" style=\"top:3px; position:relative;\" name=\"container\" value=\"mov\" onChange=\"format_changed(this);\" checked> Apple Quicktime Movie<br />";
else
echo "<input type=\"radio\" id=\"radioMov\" style=\"top:3px; position:relative;\" name=\"container\" value=\"mov\" onChange=\"format_changed(this);\"> Apple Quicktime Movie<br />";
if ($xml_format == "jpeg")
echo "<input type=\"radio\" id=\"radioJpg\" style=\"top:3px; position:relative;\" name=\"container\" value=\"jpg\" onChange=\"format_changed(this);\" checked> JPEG Sequence<br />";
else
echo "<input type=\"radio\" id=\"radioJpg\" style=\"top:3px; position:relative;\" name=\"container\" value=\"jpg\" onChange=\"format_changed(this);\"> JPEG Sequence<br />";
?>
<input id="fast_rec" type="checkbox" style="left:1px; top:3px; position:relative;" name="" value="" onChange="fast_rec_changed(this)"> Use fast recording
<a href="#" onClick="help('fast_rec');"><img src="images/help.png"></a><br />
<br />
Directory: <input id="directory" type="text" onChange="DirectoryChanged();" name="prefix" value="<? echo $xml_directory; ?>"><br />
<br />
Devices: <a href="#" onClick="scan_devices();"><img src="images/reload.png" style="bottom:-2px; position:relative;"></a><br />
<div id="ajax_devices">loading...</div>
<br />
<input id="debug" style="top:3px; position:relative;" name="debug" type="checkbox" value="yes" <? if ($xml_debug) echo "checked"; ?>>Debug File: <input name="debugfile" id="debugfile" type="text" value="<? echo $xml_debug_file ?>" size="15">
<select name="debuglevel">
<OPTION VALUE="" disabled>debug-level
<OPTION VALUE="1" <? if ($xml_debug_level == "1") echo "selected"; ?>>1
<OPTION VALUE="2" <? if ($xml_debug_level == "2") echo "selected"; ?>>2
<OPTION VALUE="3" <? if ($xml_debug_level == "3") echo "selected"; ?>>3
<OPTION VALUE="4" <? if ($xml_debug_level == "4") echo "selected"; ?>>4
<OPTION VALUE="5" <? if ($xml_debug_level == "5") echo "selected"; ?>>5
<OPTION VALUE="6" <? if ($xml_debug_level == "6") echo "selected"; ?>>6
</select>
<a href="#" onClick="help('debug');"><img src="images/help.png"></a><br />
<br />
<input name="settings_format" type="submit" value="OK">
</form>
</div>
<div class="TabbedPanelsContent">
<!-- Sound -->
<b>Audio Recording:</b><br />
<div class="small">requires external USB soundcard</div>
<p style="color:red;">not operational yet!</p>
Detected Audio Hardware: <span id="ajax_detected_audio_hardware">loading...</span> <a href="#" onClick="check_audio_hardware();"><img src="images/reload.png" style="bottom:-2px; position:relative;"></a><br />
<br />
Test Audio Playback: <a href="#" onClick="test_audio_playback('/var/hdd/Congas.wav');"><img src="images/play_audio.png" style="position:relative; top:3px;"></a><br />
<br />
<form method="POST" id="audioform">
<table cellspacing="5px">
<tr><td>Record Audio</td><td><input type="checkbox" value="on" name="audio_check" id="audio_check" disabled onChange="update_audio_form(document.getElementById('audioform'))" <? if ($xml_audiorecording_enabled == "yes") echo "checked"; ?>></td></tr>
<tr><td>Sample Rate:</td><td>
<select name="audio_sample_rate" id="audio_sample_rate" disabled>
<option <? if ($xml_audio_rate == "44100") echo "selected"; ?>>44100</option>
<option <? if ($xml_audio_rate == "22050") echo "selected"; ?>>22050</option>
<option <? if ($xml_audio_rate == "11025") echo "selected"; ?>>11025</option>
</select>
</td></tr>
<tr><td>Channels:</td><td>
<select name="audio_channels" id="audio_channels" disabled>
<option <? if ($xml_audio_channels == 2) echo "selected"; ?>>stereo</option>
<option <? if ($xml_audio_channels == 1) echo "selected"; ?>>mono</option>
</select>
</td></tr>
<tr><td>Volume:</td><td>
<select name="audio_volume" id="audio_volume" disabled>
<option value="100" <? if ($xml_audio_volume == 100) echo "selected"; ?>>100%</option>
<option value="90" <? if ($xml_audio_volume == 90) echo "selected"; ?>>90%</option>
<option value="80" <? if ($xml_audio_volume == 80) echo "selected"; ?>>80%</option>
<option value="70" <? if ($xml_audio_volume == 70) echo "selected"; ?>>70%</option>
<option value="60" <? if ($xml_audio_volume == 60) echo "selected"; ?>>60%</option>
<option value="50" <? if ($xml_audio_volume == 50) echo "selected"; ?>>50%</option>
<option value="40" <? if ($xml_audio_volume == 40) echo "selected"; ?>>40%</option>
<option value="30" <? if ($xml_audio_volume == 30) echo "selected"; ?>>30%</option>
<option value="20" <? if ($xml_audio_volume == 20) echo "selected"; ?>>20%</option>
<option value="10" <? if ($xml_audio_volume == 10) echo "selected"; ?>>10%</option>
<option value="0" <? if ($xml_audio_volume == 0) echo "selected"; ?>>0%</option>
</select> volume not working, please ignore
</td></tr>
<tr><td>Sync Mode:</td><td>
<select name="audio_syncmode" id="audio_syncmode" disabled>
<option value="normal" <? if ($xml_audio_syncmode == "no") echo "selected"; ?>>normal</option>
<option value="NFS" <? if ($xml_audio_syncmode == "yes") echo "selected"; ?>>NFS</option>
</select>
</td></tr>
<tr><td colspan="2"><INPUT name="settings_sound" type="submit" value="OK"></td></tr>
</table>
</form>
</div>
<div class="TabbedPanelsContent">
<!-- Geo-Tagging -->
<b>Geo-Tagging:</b><br />
<div class="small">requires external USB GPS-receiver</div>
<p style="color:red;">not operational yet!</p>
Detected GPS Hardware:<br />
<table cellpadding="0" cellspacing="5px">
<tr><td>Latitude:</td><td id="ajax_latitude"></td></tr>
<tr><td>Longitude:</td><td id="ajax_longitude"></td></tr>
<tr><td>Altitude:</td><td id="ajax_altitude"></td></tr>
<tr><td>Orientation:</td><td id="ajax_orientation"></td></tr>
</table>
<form method="POST">
<table cellpadding="0" cellspacing="5px">
<?
if ($xml_geotagging_enabled == "yes")
echo "<tr><td>Enable Geo-Tagging</td><td><input type=\"checkbox\" name=\"geotag_enable\" checked></td></tr>";
else
echo "<tr><td>Enable Geo-Tagging</td><td><input type=\"checkbox\" name=\"geotag_enable\"></td></tr>";
?>
<tr><td>Write GPS data every</td><td><input type="text" name="geotag_period" size="3" value="<? echo $xml_geotagging_period; ?>"> seconds</td></tr>
<tr><td>Horizontal FOV</td><td><input type="text" name="geotag_hFov" size="3" value="<? echo $xml_geotagging_hFOV*2; ?>"> &deg;</td></tr>
<tr><td>Vertical FOV</td><td><input type="text" name="geotag_vFov" size="3" value="<? echo $xml_geotagging_vFOV*2; ?>"> &deg;</td></tr>
<tr><td>Altitude Mode:</td><td><select name="geotag_altmode"><OPTION VALUE="absolute" <? if ($xml_geotagging_heightmode == "GPS altitude") echo "selected"; ?>>absolute</OPTION><OPTION VALUE="ground" <? if ($xml_geotagging_heightmode == "map ground level") echo "selected"; ?>>relative to ground</OPTION></select></td></tr>
<tr><td>Height Offset</td><td><input type="text" name="geotag_heightoffset" size="4" value="<? echo $xml_geotagging_height; ?>"> m</td></tr>
<tr><td>Near</td><td><input type="text" name="geotag_near" size="4" value="<? echo $xml_geotagging_near; ?>"></td></tr>
<tr><td colspan="2"><input name="settings_geotagging" type="submit" value="OK"></td></tr>
</table>
</form>
</div>
<div class="TabbedPanelsContent">
<!-- Advanced -->
<form method="POST">
<b>Time Settings:</b><br />
<table cellpadding="3px" cellspacing="0px;">
<tr><td>Timescale:</td><td><input id="timescale" type="text" name="timescale" size="6" value="<? echo $xml_timescale; ?>"></td><td><span class="small">currently only works for Quicktime *.mov - values > 1.0 make the video play back slower than recorded (slow motion), values < 1.0 make the playback faster (time lapse video).</span></td></tr>
<tr><td><input id="fps_reduce_frameskip" style="top:3px; position:relative;" name="fps_reduce" type="radio" value="frameskip" <? if ($xml_frameskip != 0) echo "checked"; ?> onChange="update_fps_reduce(this);"> Frameskip:</td><td><input id="frameskip_id" type="text" style="top:3px; position:relative;" name="frameskip" size="4" value="<? echo $xml_frameskip; ?>" <? if($xml_frameskip == "0") echo "disabled"; ?>></td><td><span class="small">reduces framerate and skips every n frames.</span></td></tr>
<tr><td width="100px;"><input id="fps_reduce_timelapse" name="fps_reduce" type="radio" style="top:3px; position:relative;" value="timelapse" <? if ($xml_timelapse != 0) echo "checked"; ?> onChange="update_fps_reduce(this);"> Timelapse:</td><td><input size="4" style="top:3px; position:relative;" id="timelapse_id" type="text" name="timelapse" value="<? echo $xml_timelapse; ?>" <? if($xml_timelapse == "0") echo "disabled"; ?>></td><td><span class="small">reduces framerate and waits n seconds between recording single frames.</span></td></tr>
<tr><td></td></tr>
<tr><td>Save EXIF data</td><td><input name="exif" type="checkbox" value="yes" <? if ($xml_exif == "\"yes\"") echo "checked";?>></td></tr>
<tr><td>Split Size:</td><td><input name="split_size" id="split_size_input" type="text" size="10" onChange="calc_split_size();" onkeyup="calc_split_size();" onBlur="calc_split_size();" value="<? echo $xml_split_size; ?>" ></td><td>Bytes <span class="small" id="split_size_calculation">...</span></td></tr>
<tr><td>Split Length:</td><td><input name="split_length" type="text" size="10" value="<? echo $xml_split_length; ?>"></td><td>Seconds</td></tr>
</table>
<INPUT name="advanced_settings" type="submit" value="OK">
</div>
</form>
</div>
</div>
</div>
</td>
</table>
</div>
<script type="text/javascript">
<!--
if (getCookie('live_image_panel_open') == "true")
var CollapsiblePanel1 = new Spry.Widget.CollapsiblePanel("CollapsiblePanel1", {contentIsOpen:true});
else
var CollapsiblePanel1 = new Spry.Widget.CollapsiblePanel("CollapsiblePanel1", {contentIsOpen:false});
var TabbedPanels1 = new Spry.Widget.TabbedPanels("TabbedPanels1");
if (getCookie('tab') != "")
TabbedPanels1.showPanel(parseInt(getCookie('tab')));
//-->
</script>
</body>
<?
/* xml-simple.php
Simple XML Parser for PHP by Rogers Cadenhead, derived from
original code by Jim Winstead Jr.
Version 1.01
Web: http://www.cadenhead.org/workbench/xml-simple
Copyright (C) 2005 Rogers Cadenhead
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
if (__FILE__ == $PATH_TRANSLATED) {
header("Status: 403 Forbidden");
exit();
}
// a PHP class library that parses XML data
class xml_simple {
/* an array that holds parsed XML data as either name-value pairs (for character data) or arrays (for subelements) */
var $tree = array();
var $force_to_array = array();
// a descriptive error message, if the class fails to execute successfully
var $error = null;
// Create the XML parser that will read XML data formatted with the specified encoding
function xml_simple($encoding = 'UTF-8') {
$this->parser = xml_parser_create($encoding);
xml_set_object($this->parser, $this);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
xml_set_element_handler($this->parser, "start_element", "stop_element");
xml_set_character_data_handler($this->parser, "char_data");
}
function force_to_array() {
for ($i = 0; $i < func_num_args(); $i++) {
$this->force_to_array[] = func_get_arg($i);
}
}
/* Parse XML data, storing it in the instance variable; returns false if the data cannot be parsed. */
function parse($data) {
$this->tree = array();
if (!xml_parse($this->parser, $data, 1)) {
$this->error = "xml parse error: " .
xml_error_string(xml_get_error_code($this->parser)) .
" on line ".xml_get_current_line_number($this->parser);
return false;
}
return $this->tree[0]["content"];
}
function parse_file($file) {
$fp = @fopen($file, "r");
if (!$fp) {
user_error("unable to open file: '$file'");
return false;
}
while ($data = fread($fp, 4096)) {
if (!xml_parse($this->parser, $data, feof($fp))) {
user_error("xml parse error: " .
xml_error_string(xml_get_error_code($this->parser)) .
" on line " . xml_get_current_line_number($this->parser));
}
}
fclose($fp);
return $this->tree[0]["content"];
}
function encode_as_xml($value) {
if (is_array($value)) {
reset($value); $out = '';
while (list($key,$val) = each($value)) {
if (is_array($val) && isset($val[0])) {
reset($val);
while (list(,$item) = each($val)) {
$out .= "<$key>".xml_simple::encode_as_xml($item)."</$key>";
}
} else {
$out .= "<$key>".xml_simple::encode_as_xml($val)."</$key>";
}
}
return $out;
} else {
return htmlspecialchars($value);
}
}
function start_element($parser, $name, $attrs) {
array_unshift($this->tree, array("name" => $name));
}
function stop_element($parser, $name) {
if ($name != $this->tree[0]["name"]) die("incorrect nesting");
if (count($this->tree) > 1) {
$elem = array_shift($this->tree);
if (isset($this->tree[0]["content"][$elem["name"]])) {
if (is_array($this->tree[0]["content"][$elem["name"]]) && isset($this->tree[0]["content"][$elem["name"]][0])) {
array_push($this->tree[0]["content"][$elem["name"]], $elem["content"]);
} else {
$this->tree[0]["content"][$elem["name"]] =
array($this->tree[0]["content"][$elem["name"]],$elem["content"]);
}
} else {
if (in_array($elem["name"],$this->force_to_array)) {
$this->tree[0]["content"][$elem["name"]] = array($elem["content"]);
} else {
if (!isset($elem["content"])) $elem["content"] = "";
$this->tree[0]["content"][$elem["name"]] = $elem["content"];
}
}
}
}
function char_data($parser, $data) {
# don't add a string to non-string data
if (!is_string($this->tree[0]["content"]) && !preg_match("/\\S/", $data)) return;
$this->tree[0]["content"] .= $data;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment