Merge pull request #2901 from hax0kartik/253-vnc

Add vnc as a camera type.
pull/2905/head
Isaac Connor 2020-03-30 08:12:47 -04:00 committed by GitHub
commit 53470ed30b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 319 additions and 30 deletions

View File

@ -187,6 +187,8 @@ set(ZM_NO_MMAP "OFF" CACHE BOOL
experience problems with the shared memory. default: OFF")
set(ZM_NO_LIBVLC "OFF" CACHE BOOL
"Set to ON to skip libvlc checks and force building ZM without libvlc. default: OFF")
set(ZM_NO_LIBVNC "OFF" CACHE BOOL
"Set to ON to skip libvnc checks and force building ZM without libvnc. default: OFF")
set(ZM_NO_CURL "OFF" CACHE BOOL
"Set to ON to skip cURL checks and force building ZM without cURL. default: OFF")
set(ZM_NO_X10 "OFF" CACHE BOOL
@ -674,6 +676,25 @@ if(NOT ZM_NO_LIBVLC)
endif(LIBVLC_LIBRARIES)
endif(NOT ZM_NO_LIBVLC)
if(NOT ZM_NO_LIBVNC)
# libvncclient (using find_library and find_path)
find_library(LIBVNC_LIBRARIES vncclient)
if(LIBVNC_LIBRARIES)
set(HAVE_LIBVNC 1)
list(APPEND ZM_BIN_LIBS "${LIBVNC_LIBRARIES}")
find_path(LIBVNC_INCLUDE_DIR "rfb/rfb.h")
if(LIBVNC_INCLUDE_DIR)
include_directories("${LIBVNC_INCLUDE_DIR}")
set(CMAKE_REQUIRED_INCLUDES "${LIBVNC_INCLUDE_DIR}")
endif(LIBVNC_INCLUDE_DIR)
mark_as_advanced(FORCE LIBVNC_LIBRARIES LIBVNC_INCLUDE_DIR)
check_include_file("rfb/rfb.h" HAVE_RFB_RFB_H)
set(optlibsfound "${optlibsfound} libVNC")
else(LIBVNC_LIBRARIES)
set(optlibsnotfound "${optlibsnotfound} libVNC")
endif(LIBVNC_LIBRARIES)
endif(NOT ZM_NO_LIBVNC)
#find_package(Boost 1.36.0)
#if(Boost_FOUND)
#include_directories(${Boost_INCLUDE_DIRS})

View File

@ -63,7 +63,7 @@ DROP TABLE IF EXISTS `Controls`;
CREATE TABLE `Controls` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
`Protocol` varchar(64) default NULL,
`CanWake` tinyint(3) unsigned NOT NULL default '0',
`CanSleep` tinyint(3) unsigned NOT NULL default '0',
@ -406,7 +406,7 @@ DROP TABLE IF EXISTS `MonitorPresets`;
CREATE TABLE `MonitorPresets` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
`Device` tinytext,
`Channel` tinyint(3) unsigned default NULL,
`Format` int(10) unsigned default NULL,
@ -440,7 +440,7 @@ CREATE TABLE `Monitors` (
`Notes` TEXT,
`ServerId` int(10) unsigned,
`StorageId` smallint(5) unsigned default 0,
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket') NOT NULL default 'Local',
`Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite','NVSocket','VNC') NOT NULL default 'Local',
`Function` enum('None','Monitor','Modect','Record','Mocord','Nodect') NOT NULL default 'Monitor',
`Enabled` tinyint(3) unsigned NOT NULL default '1',
`LinkedMonitors` varchar(255),

1
db/zm_update-1.35.2.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE Monitors MODIFY `Type` enum('Local','Remote','File','Ffmpeg','Libvlc','cURL','NVSocket','VNC') NOT NULL default 'Local';

View File

@ -28,7 +28,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.35.1
Version: 1.35.2
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@ -4,7 +4,7 @@
configure_file(zm_config.h.in "${CMAKE_CURRENT_BINARY_DIR}/zm_config.h" @ONLY)
# Group together all the source files that are used by all the binaries (zmc, zma, zmu, zms etc)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
set(ZM_BIN_SRC_FILES zm_box.cpp zm_buffer.cpp zm_camera.cpp zm_comms.cpp zm_config.cpp zm_coord.cpp zm_curl_camera.cpp zm.cpp zm_db.cpp zm_logger.cpp zm_event.cpp zm_frame.cpp zm_eventstream.cpp zm_exception.cpp zm_file_camera.cpp zm_ffmpeg_input.cpp zm_ffmpeg_camera.cpp zm_group.cpp zm_image.cpp zm_jpeg.cpp zm_libvlc_camera.cpp zm_libvnc_camera.cpp zm_local_camera.cpp zm_monitor.cpp zm_monitorstream.cpp zm_ffmpeg.cpp zm_mpeg.cpp zm_packet.cpp zm_packetqueue.cpp zm_poly.cpp zm_regexp.cpp zm_remote_camera.cpp zm_remote_camera_http.cpp zm_remote_camera_nvsocket.cpp zm_remote_camera_rtsp.cpp zm_rtp.cpp zm_rtp_ctrl.cpp zm_rtp_data.cpp zm_rtp_source.cpp zm_rtsp.cpp zm_rtsp_auth.cpp zm_sdp.cpp zm_signal.cpp zm_stream.cpp zm_swscale.cpp zm_thread.cpp zm_time.cpp zm_timer.cpp zm_user.cpp zm_utils.cpp zm_video.cpp zm_videostore.cpp zm_zone.cpp zm_storage.cpp zm_fifo.cpp zm_crypt.cpp)
# A fix for cmake recompiling the source files for every target.

View File

@ -35,7 +35,7 @@ class Camera;
//
class Camera {
protected:
typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC } SourceType;
typedef enum { LOCAL_SRC, REMOTE_SRC, FILE_SRC, FFMPEG_SRC, LIBVLC_SRC, CURL_SRC, VNC_SRC } SourceType;
unsigned int monitor_id;
Monitor * monitor; // Null on instantiation, set as soon as possible.
@ -68,6 +68,7 @@ public:
bool IsFfmpeg() const { return type == FFMPEG_SRC; }
bool IsLibvlc() const { return type == LIBVLC_SRC; }
bool IscURL() const { return type == CURL_SRC; }
bool IsVNC() const { return type == VNC_SRC; }
unsigned int Width() const { return width; }
unsigned int Height() const { return height; }
unsigned int Colours() const { return colours; }

149
src/zm_libvnc_camera.cpp Normal file
View File

@ -0,0 +1,149 @@
#include "zm.h"
#include "zm_signal.h"
#include "zm_libvnc_camera.h"
#include "zm_swscale.h"
#if HAVE_LIBVNC
static int TAG_0;
static int TAG_1;
static int TAG_2;
static void GotFrameBufferUpdateCallback(rfbClient *rfb, int x, int y, int w, int h){
VncPrivateData *data = (VncPrivateData *)rfbClientGetClientData(rfb, &TAG_0);
data->buffer = rfb->frameBuffer;
}
static char* GetPasswordCallback(rfbClient* cl){
return strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
}
static rfbCredential* GetCredentialsCallback(rfbClient* cl, int credentialType){
rfbCredential *c = (rfbCredential *)malloc(sizeof(rfbCredential));
if ( credentialType != rfbCredentialTypeUser ) {
free(c);
return NULL;
}
c->userCredential.password = strdup((const char *)rfbClientGetClientData(cl, &TAG_1));
c->userCredential.username = strdup((const char *)rfbClientGetClientData(cl, &TAG_2));
return c;
}
VncCamera::VncCamera(
unsigned int p_monitor_id,
const std::string &host,
const std::string &port,
const std::string &user,
const std::string &pass,
int p_width,
int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio ) :
Camera(
p_monitor_id,
VNC_SRC,
p_width,
p_height,
p_colours,
ZM_SUBPIX_ORDER_DEFAULT_FOR_COLOUR(p_colours),
p_brightness,
p_contrast,
p_hue,
p_colour,
p_capture,
p_record_audio
),
mHost(host),
mPort(port),
mUser(user),
mPass(pass)
{
Debug(2, "Host:%s Port: %s User: %s Pass:%s", mHost.c_str(), mPort.c_str(), mUser.c_str(), mPass.c_str());
if ( colours == ZM_COLOUR_RGB32 ) {
subpixelorder = ZM_SUBPIX_ORDER_RGBA;
mImgPixFmt = AV_PIX_FMT_RGBA;
mBpp = 4;
} else if ( colours == ZM_COLOUR_RGB24 ) {
subpixelorder = ZM_SUBPIX_ORDER_RGB;
mImgPixFmt = AV_PIX_FMT_RGB24;
mBpp = 3;
} else if ( colours == ZM_COLOUR_GRAY8 ) {
subpixelorder = ZM_SUBPIX_ORDER_NONE;
mImgPixFmt = AV_PIX_FMT_GRAY8;
mBpp = 1;
} else {
Panic("Unexpected colours: %d", colours);
}
if ( capture )
Initialise();
}
VncCamera::~VncCamera() {
if( capture )
Terminate();
}
void VncCamera::Initialise() {
Debug(2, "Initializing Client");
mRfb = rfbGetClient(8, 3, 4);
rfbClientSetClientData(mRfb, &TAG_0, &mVncData);
rfbClientSetClientData(mRfb, &TAG_1, (void *)mPass.c_str());
rfbClientSetClientData(mRfb, &TAG_2, (void *)mUser.c_str());
mRfb->GotFrameBufferUpdate = GotFrameBufferUpdateCallback;
mRfb->GetPassword = GetPasswordCallback;
mRfb->GetCredential = GetCredentialsCallback;
mRfb->programName = "Zoneminder VNC Monitor";
mRfb->serverHost = strdup(mHost.c_str());
mRfb->serverPort = atoi(mPort.c_str());
rfbInitClient(mRfb, 0, nullptr);
scale.init();
}
void VncCamera::Terminate() {
return;
}
int VncCamera::PrimeCapture() {
Info("Priming capture from %s", mHost.c_str());
return 0;
}
int VncCamera::PreCapture() {
Debug(2, "PreCapture");
WaitForMessage(mRfb, 500);
rfbBool res = HandleRFBServerMessage(mRfb);
return res == TRUE ? 1 : -1 ;
}
int VncCamera::Capture(Image &image) {
Debug(2, "Capturing");
uint8_t *directbuffer = image.WriteBuffer(width, height, colours, subpixelorder);
scale.Convert(mVncData.buffer, mRfb->si.framebufferHeight * mRfb->si.framebufferWidth * 4, directbuffer, width * height * mBpp, AV_PIX_FMT_RGBA, mImgPixFmt, mRfb->si.framebufferWidth, mRfb->si.framebufferHeight, width, height);
return 1;
}
int VncCamera::PostCapture() {
return 0;
}
int VncCamera::CaptureAndRecord(Image &image, timeval recording, char* event_directory) {
return 0;
}
int VncCamera::Close() {
rfbClientCleanup(mRfb);
return 0;
}
#endif

69
src/zm_libvnc_camera.h Normal file
View File

@ -0,0 +1,69 @@
#ifndef ZN_LIBVNC_CAMERA_H
#define ZN_LIBVNC_CAMERA_H
#include "zm_buffer.h"
#include "zm_camera.h"
#include "zm_thread.h"
#include "zm_swscale.h"
#if HAVE_LIBVNC
#include <rfb/rfbclient.h>
extern "C" {
#include <libavutil/imgutils.h>
#include <libavutil/parseutils.h>
#include <libswscale/swscale.h>
}
// Used by vnc callbacks
struct VncPrivateData
{
uint8_t *buffer;
uint8_t width;
uint8_t height;
};
class VncCamera : public Camera {
protected:
rfbClient *mRfb;
VncPrivateData mVncData;
int mBpp;
SWScale scale;
AVPixelFormat mImgPixFmt;
std::string mHost;
std::string mPort;
std::string mUser;
std::string mPass;
public:
VncCamera(
unsigned int p_monitor_id,
const std::string &host,
const std::string &port,
const std::string &user,
const std::string &pass,
int p_width,
int p_height,
int p_colours,
int p_brightness,
int p_contrast,
int p_hue,
int p_colour,
bool p_capture,
bool p_record_audio );
~VncCamera();
void Initialise();
void Terminate();
int PreCapture();
int PrimeCapture();
int Capture( Image &image );
int PostCapture();
int CaptureAndRecord( Image &image, timeval recording, char* event_directory );
int Close();
};
#endif // HAVE_LIBVNC
#endif // ZN_LIBVNC_CAMERA_H

View File

@ -51,6 +51,9 @@
#if HAVE_LIBCURL
#include "zm_curl_camera.h"
#endif // HAVE_LIBCURL
#if HAVE_LIBVNC
#include "zm_libvnc_camera.h"
#endif // HAVE_LIBVNC
#if ZM_MEM_MAPPED
#include <sys/mman.h>
@ -89,6 +92,7 @@ std::string CameraType_Strings[] = {
"Ffmpeg",
"LibVLC",
"CURL",
"VNC",
};
@ -2332,6 +2336,27 @@ Monitor *Monitor::Load(MYSQL_ROW dbrow, bool load_zones, Purpose purpose) {
#else // HAVE_LIBCURL
Fatal("You must have libcurl installed to use ffmpeg cameras for monitor %d", id);
#endif // HAVE_LIBCURL
} else if ( type == "VNC" ) {
#if HAVE_LIBVNC
camera = new VncCamera(
id,
host.c_str(),
port.c_str(),
user.c_str(),
pass.c_str(),
width,
height,
colours,
brightness,
contrast,
hue,
colour,
purpose==CAPTURE,
record_audio
);
#else // HAVE_LIBVNC
Fatal("You must have libvnc installed to use VNC cameras for monitor id %d", id);
#endif // HAVE_LIBVNC
} else {
Fatal("Bogus monitor type '%s' for monitor %d", type.c_str(), id);
} // end if type

View File

@ -75,6 +75,7 @@ public:
FFMPEG,
LIBVLC,
CURL,
VNC,
} CameraType;
typedef enum {

View File

@ -84,7 +84,7 @@ int SWScale::SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf,
return 0;
}
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height) {
/* Parameter checking */
if(in_buffer == NULL || out_buffer == NULL) {
Error("NULL Input or output buffer");
@ -94,7 +94,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
// Error("Invalid input or output pixel formats");
// return -2;
// }
if (!width || !height) {
if (!width || !height || !new_height || !new_width) {
Error("Invalid width or height");
return -3;
}
@ -111,7 +111,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
/* Check the buffer sizes */
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t insize = av_image_get_buffer_size(in_pf, width, height,1);
size_t insize = av_image_get_buffer_size(in_pf, width, height, 1);
#else
size_t insize = avpicture_get_size(in_pf, width, height);
#endif
@ -120,9 +120,9 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
return -4;
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
size_t outsize = av_image_get_buffer_size(out_pf, width, height,1);
size_t outsize = av_image_get_buffer_size(out_pf, new_width, new_height, 1);
#else
size_t outsize = avpicture_get_size(out_pf, width, height);
size_t outsize = avpicture_get_size(out_pf, new_width, new_height);
#endif
if(outsize < out_buffer_size) {
@ -131,7 +131,7 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
}
/* Get the context */
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, width, height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
swscale_ctx = sws_getCachedContext( swscale_ctx, width, height, in_pf, new_width, new_height, out_pf, SWS_FAST_BILINEAR, NULL, NULL, NULL );
if(swscale_ctx == NULL) {
Error("Failed getting swscale context");
return -6;
@ -150,10 +150,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
}
#if LIBAVUTIL_VERSION_CHECK(54, 6, 0, 6, 0)
if (av_image_fill_arrays(output_avframe->data, output_avframe->linesize,
out_buffer, out_pf, width, height, 1) <= 0) {
out_buffer, out_pf, new_width, new_height, 1) <= 0) {
#else
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, width,
height) <= 0) {
if (avpicture_fill((AVPicture*) output_avframe, out_buffer, out_pf, new_width,
new_height) <= 0) {
#endif
Error("Failed filling output frame with output buffer");
return -8;
@ -168,6 +168,10 @@ int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint
return 0;
}
int SWScale::Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
return Convert(in_buffer, in_buffer_size, out_buffer, out_buffer_size, in_pf, out_pf, width, height, width, height);
}
int SWScale::Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height) {
if(img->Width() != width) {
Error("Source image width differs. Source: %d Output: %d",img->Width(), width);

View File

@ -10,13 +10,14 @@ class SWScale {
public:
SWScale();
~SWScale();
bool init();
bool init();
int SetDefaults(enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int ConvertDefaults(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size);
int ConvertDefaults(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size);
int Convert(const Image* img, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height);
int Convert(const uint8_t* in_buffer, const size_t in_buffer_size, uint8_t* out_buffer, const size_t out_buffer_size, enum _AVPIXELFORMAT in_pf, enum _AVPIXELFORMAT out_pf, unsigned int width, unsigned int height, unsigned int new_width, unsigned int new_height);
protected:
bool gotdefaults;
struct SwsContext* swscale_ctx;

View File

@ -1 +1 @@
1.35.1
1.35.2

View File

@ -119,7 +119,7 @@ class Monitor extends AppModel {
);
public $actsAs = array(
'CakePHP-Enum-Behavior.Enum' => array(
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite'),
'Type' => array('Local','Remote','File','Ffmpeg','Libvlc','cURL','WebSite', 'VNC'),
'Function' => array('None','Monitor','Modect','Record','Mocord','Nodect'),
'Orientation' => array('ROTATE_0','ROTATE_90','ROTATE_180','ROTATE_270','FLIP_HORI','FLIP_VERT'),
'OutputCodec' => array('h264','mjpeg','mpeg1','mpeg2'),

View File

@ -36,7 +36,7 @@ if ( isset($_REQUEST['object']) ) {
}
$Layout->Positions($_REQUEST['Positions']);
$Layout->save();
session_start();
zm_session_start();
$_SESSION['zmMontageLayout'] = $Layout->Id();
setcookie('zmMontageLayout', $Layout->Id(), 1);
session_write_close();

View File

@ -210,7 +210,6 @@ function Monitor(monitorData) {
* @param {*} element - the event data passed by onchange callback
*/
function selectLayout(element) {
console.log(element);
layout = $j(element).val();
if ( layout_id = parseInt(layout) ) {
@ -221,8 +220,8 @@ function selectLayout(element) {
// Need to clear the current positioning, and apply the new
monitor_frame = $j('#monitorFrame'+monitor.id);
if ( ! monitor_frame ) {
console.log("Error finding frame for " + monitor.id);
if ( !monitor_frame ) {
console.log('Error finding frame for ' + monitor.id);
continue;
}
@ -262,6 +261,10 @@ function selectLayout(element) {
if ( streamImg.nodeName == 'IMG' ) {
var src = streamImg.src;
src = src.replace(/width=[\.\d]+/i, 'width=0' );
if ( $j('#height').val() == 'auto' ) {
src = src.replace(/height=[\.\d]+/i, 'height=0' );
streamImg.style.height = 'auto';
}
if ( src != streamImg.src ) {
streamImg.src = '';
streamImg.src = src;

View File

@ -123,7 +123,8 @@ $sourceTypes = array(
'Libvlc' => translate('Libvlc'),
'cURL' => 'cURL (HTTP(S) only)',
'WebSite'=> 'Web Site',
'NVSocket' => translate('NVSocket')
'NVSocket' => translate('NVSocket'),
'VNC' => 'VNC'
);
if ( !ZM_HAS_V4L )
unset($sourceTypes['Local']);
@ -779,6 +780,13 @@ switch ( $tab ) {
} else if ( $monitor->Type() == 'NVSocket' ) {
include('_monitor_source_nvsocket.php');
} else if ( $monitor->Type() == 'VNC' ) {
?>
<tr><td><?php echo translate('Host Addr') ?></td><td><input type="text" name="newMonitor[Host]" value="<?php echo validHtmlStr($monitor->Host()) ?>" size="36"/></td></tr>
<tr><td><?php echo translate('Host Port') ?></td><td><input type="number" name="newMonitor[Port]" value="<?php echo validHtmlStr($monitor->Port()) ?>" size="6"/></td></tr>
<tr><td><?php echo 'Username' ?></td><td><input type="text" name="newMonitor[User]" value="<?php echo validHtmlStr($monitor->User()) ?>" size="12"/></td></tr>
<tr><td><?php echo 'Password' ?></td><td><input type="text" name="newMonitor[Pass]" value="<?php echo validHtmlStr($monitor->Pass()) ?>" size="12"/></td></tr>
<?php
} else if ( $monitor->Type() == 'Remote' ) {
?>
<tr><td><?php echo translate('RemoteProtocol') ?></td><td><?php echo htmlSelect( "newMonitor[Protocol]", $remoteProtocols, $monitor->Protocol(), "updateMethods( this );if(this.value=='rtsp'){\$('RTSPDescribe').setStyle('display','table-row');}else{\$('RTSPDescribe').hide();}" ); ?></td></tr>
@ -811,8 +819,8 @@ include('_monitor_source_nvsocket.php');
?>
<tr><td><?php echo translate('WebSiteUrl') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
<tr><td><?php echo translate('Width') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Width]" value="<?php echo validHtmlStr($monitor->Width()) ?>" size="4";"/></td></tr>
<tr><td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4";"/></td></tr>
<tr><td><?php echo 'Web Site Refresh (Optional)' ?></td><td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()); ?>"/></td></tr>
<tr><td><?php echo translate('Height') ?> (<?php echo translate('Pixels') ?>)</td><td><input type="text" name="newMonitor[Height]" value="<?php echo validHtmlStr($monitor->Height()) ?>" size="4";"/></td></tr>
<tr><td><?php echo 'Web Site Refresh (Optional)' ?></td><td><input type="number" name="newMonitor[Refresh]" value="<?php echo validHtmlStr($monitor->Refresh()); ?>"/></td></tr>
<?php
} elseif ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
?>

View File

@ -66,17 +66,19 @@ foreach ( $layouts as $l ) {
}
}
foreach ( $layouts as $l ) {
if ( $l->Name() != "Freeform" )
if ( $l->Name() != 'Freeform' )
$layoutsById[$l->Id()] = $l;
}
session_start();
zm_session_start();
$layout_id = '';
if ( isset($_COOKIE['zmMontageLayout']) ) {
$layout_id = $_SESSION['zmMontageLayout'] = $_COOKIE['zmMontageLayout'];
#} elseif ( isset($_SESSION['zmMontageLayout']) ) {
#$layout_id = $_SESSION['zmMontageLayout'];
ZM\Logger::Debug("Using layout $layout_id");
} elseif ( isset($_SESSION['zmMontageLayout']) ) {
$layout_id = $_SESSION['zmMontageLayout'];
ZM\Logger::Debug("Using layout $layout_id from session");
}
$options = array();
@ -85,6 +87,8 @@ $Positions = '';
if ( $layout_id and is_numeric($layout_id) and isset($layoutsById[$layout_id]) ) {
$Layout = $layoutsById[$layout_id];
$Positions = json_decode($Layout->Positions(), true);
} else {
ZM\Logger::Debug("Layout not found");
}
if ( $Layout and ( $Layout->Name() != 'Freeform' ) ) {
// Use layout instead of other options

View File

@ -59,6 +59,8 @@
#cmakedefine HAVE_LIBAVRESAMPLE_AVRESAMPLE_H 1
#cmakedefine HAVE_LIBVLC 1
#cmakedefine HAVE_VLC_VLC_H 1
#cmakedefine HAVE_LIBVNC 1
#cmakedefine HAVE_RFB_RFB_H 1
#cmakedefine HAVE_LIBX264 1
#cmakedefine HAVE_X264_H 1
#cmakedefine HAVE_LIBMP4V2 1