Bug 374 - Multiple monitors can now share the same video device source without penalty.

git-svn-id: http://svn.zoneminder.com/svn/zm/trunk@2030 e3e1d417-86f3-4887-817a-d78f3d33393f
This commit is contained in:
stan
2006-10-24 14:37:34 +00:00
parent 16e0383c54
commit ed0626492f
8 changed files with 304 additions and 264 deletions

View File

@@ -68,6 +68,7 @@ public:
bool CanCapture() const { return( capture ); }
virtual int PrimeCapture() { return( 0 ); }
virtual int PreCapture()=0;
virtual int PostCapture( Image &image )=0;
};

View File

@@ -28,6 +28,9 @@
#include "zm_local_camera.h"
int LocalCamera::camera_count = 0;
int LocalCamera::channel_count = 0;
int LocalCamera::last_channel = -1;
int LocalCamera::m_cap_frame = 0;
int LocalCamera::m_cap_frame_active = 0;
int LocalCamera::m_sync_frame = 0;
@@ -50,6 +53,16 @@ LocalCamera::LocalCamera( const char *p_device, int p_channel, int p_format, int
{
Initialise();
}
if ( channel != last_channel )
{
channel_index = 0;
channel_count++;
last_channel = channel;
}
else
{
channel_index = 1;
}
}
LocalCamera::~LocalCamera()
@@ -534,11 +547,20 @@ int LocalCamera::Contrast( int p_contrast )
return( vid_pic.contrast );
}
int LocalCamera::PrimeCapture()
{
if ( channel_count == 1 && channel_index == 0 )
{
return( PreCapture() );
}
return( 0 );
}
int LocalCamera::PreCapture()
{
//Info(( "%s: Capturing image", id ));
if ( camera_count > 1 )
if ( channel_count > 1 )
{
//Info(( "Switching" ));
struct video_channel vid_src;
@@ -560,285 +582,296 @@ int LocalCamera::PreCapture()
return( -1 );
}
}
m_cap_frame_active = m_cap_frame;
if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
{
Error(( "Capture failure for frame %d: %s", m_cap_frame_active, strerror(errno) ));
return( -1 );
}
m_cap_frame = (m_cap_frame+1)%m_vmb.frames;
if ( channel_count > 1 || channel_index == 0 )
{
//Info(( "Pre-Capture" ));
m_cap_frame_active = m_cap_frame;
if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
{
Error(( "Capture failure for frame %d: %s", m_cap_frame_active, strerror(errno) ));
return( -1 );
}
m_cap_frame = (m_cap_frame+1)%m_vmb.frames;
}
return( 0 );
}
int LocalCamera::PostCapture( Image &image )
{
static unsigned char *buffer = 0;
//Info(( "%s: Capturing image", id ));
int captures_per_frame = 1;
if ( camera_count > 1 )
if ( channel_count > 1 )
captures_per_frame = config.captures_per_frame;
while ( captures_per_frame )
{
if ( ioctl( m_videohandle, VIDIOCSYNC, &m_sync_frame ) < 0 )
{
Error(( "Sync failure for frame %d buffer %d(%d): %s", m_sync_frame, m_cap_frame_active, captures_per_frame, strerror(errno) ));
return( -1 );
}
captures_per_frame--;
if ( captures_per_frame )
{
if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
{
Error(( "Capture failure for buffer %d(%d): %s", m_cap_frame_active, captures_per_frame, strerror(errno) ));
return( -1 );
}
}
}
//Info(( "Captured %d for %d into %d", m_sync_frame, channel, m_cap_frame_active));
if ( channel_count > 1 || channel_index == 0 )
{
//Info(( "Post-Capture" ));
while ( captures_per_frame )
{
if ( ioctl( m_videohandle, VIDIOCSYNC, &m_sync_frame ) < 0 )
{
Error(( "Sync failure for frame %d buffer %d(%d): %s", m_sync_frame, m_cap_frame_active, captures_per_frame, strerror(errno) ));
return( -1 );
}
captures_per_frame--;
if ( captures_per_frame )
{
if ( ioctl( m_videohandle, VIDIOCMCAPTURE, &m_vmm[m_cap_frame_active] ) < 0 )
{
Error(( "Capture failure for buffer %d(%d): %s", m_cap_frame_active, captures_per_frame, strerror(errno) ));
return( -1 );
}
}
}
//Info(( "Captured %d for %d into %d", m_sync_frame, channel, m_cap_frame_active));
unsigned char *buffer = m_buffer+(m_sync_frame*m_vmb.size/m_vmb.frames);
m_sync_frame = (m_sync_frame+1)%m_vmb.frames;
buffer = m_buffer+(m_sync_frame*m_vmb.size/m_vmb.frames);
m_sync_frame = (m_sync_frame+1)%m_vmb.frames;
static unsigned char temp_buffer[ZM_MAX_IMAGE_SIZE];
switch( palette )
{
case VIDEO_PALETTE_YUV420P :
{
static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM];
static char v_plane[ZM_MAX_IMAGE_DIM];
static unsigned char temp_buffer[ZM_MAX_IMAGE_SIZE];
switch( palette )
{
case VIDEO_PALETTE_YUV420P :
{
static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM];
static char v_plane[ZM_MAX_IMAGE_DIM];
unsigned char *rgb_ptr = temp_buffer;
unsigned char *y_ptr = y_plane;
char *u1_ptr = u_plane;
char *u2_ptr = u_plane+width;
char *v1_ptr = v_plane;
char *v2_ptr = v_plane+width;
unsigned char *rgb_ptr = temp_buffer;
unsigned char *y_ptr = y_plane;
char *u1_ptr = u_plane;
char *u2_ptr = u_plane+width;
char *v1_ptr = v_plane;
char *v2_ptr = v_plane+width;
int Y_size = width*height;
int C_size = Y_size>>2; // Every little bit helps...
unsigned char *Y_ptr = buffer;
unsigned char *Cb_ptr = buffer + Y_size;
unsigned char *Cr_ptr = Cb_ptr + C_size;
int y,u,v;
for ( int i = 0; i < Y_size; i++ )
{
*y_ptr++ = y_table[*Y_ptr++];
}
int half_width = width>>1; // We are the king of optimisations!
for ( int i = 0, j = 0; i < C_size; i++, j++ )
{
if ( j == half_width )
{
j = 0;
u1_ptr += width;
u2_ptr += width;
v1_ptr += width;
v2_ptr += width;
}
u = uv_table[*Cb_ptr++];
int Y_size = width*height;
int C_size = Y_size>>2; // Every little bit helps...
unsigned char *Y_ptr = buffer;
unsigned char *Cb_ptr = buffer + Y_size;
unsigned char *Cr_ptr = Cb_ptr + C_size;
int y,u,v;
for ( int i = 0; i < Y_size; i++ )
{
*y_ptr++ = y_table[*Y_ptr++];
}
int half_width = width>>1; // We are the king of optimisations!
for ( int i = 0, j = 0; i < C_size; i++, j++ )
{
if ( j == half_width )
{
j = 0;
u1_ptr += width;
u2_ptr += width;
v1_ptr += width;
v2_ptr += width;
}
u = uv_table[*Cb_ptr++];
*u1_ptr++ = u;
*u1_ptr++ = u;
*u2_ptr++ = u;
*u2_ptr++ = u;
*u1_ptr++ = u;
*u1_ptr++ = u;
*u2_ptr++ = u;
*u2_ptr++ = u;
v = uv_table[*Cr_ptr++];
v = uv_table[*Cr_ptr++];
*v1_ptr++ = v;
*v1_ptr++ = v;
*v2_ptr++ = v;
*v2_ptr++ = v;
}
*v1_ptr++ = v;
*v1_ptr++ = v;
*v2_ptr++ = v;
*v2_ptr++ = v;
}
y_ptr = y_plane;
u1_ptr = u_plane;
v1_ptr = v_plane;
int size = Y_size*3;
int r,g,b;
for ( int i = 0; i < size; i += 3 )
{
y = *y_ptr++;
u = *u1_ptr++;
v = *v1_ptr++;
y_ptr = y_plane;
u1_ptr = u_plane;
v1_ptr = v_plane;
int size = Y_size*3;
int r,g,b;
for ( int i = 0; i < size; i += 3 )
{
y = *y_ptr++;
u = *u1_ptr++;
v = *v1_ptr++;
r = y + r_v_table[v];
g = y - (g_u_table[u]+g_v_table[v]);
b = y + b_u_table[u];
r = y + r_v_table[v];
g = y - (g_u_table[u]+g_v_table[v]);
b = y + b_u_table[u];
*rgb_ptr++ = r<0?0:(r>255?255:r);
*rgb_ptr++ = g<0?0:(g>255?255:g);
*rgb_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_YUV422P :
{
static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM];
static char v_plane[ZM_MAX_IMAGE_DIM];
*rgb_ptr++ = r<0?0:(r>255?255:r);
*rgb_ptr++ = g<0?0:(g>255?255:g);
*rgb_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_YUV422P :
{
static unsigned char y_plane[ZM_MAX_IMAGE_DIM];
static char u_plane[ZM_MAX_IMAGE_DIM];
static char v_plane[ZM_MAX_IMAGE_DIM];
unsigned char *rgb_ptr = temp_buffer;
unsigned char *y_ptr = y_plane;
char *u1_ptr = u_plane;
char *v1_ptr = v_plane;
unsigned char *rgb_ptr = temp_buffer;
unsigned char *y_ptr = y_plane;
char *u1_ptr = u_plane;
char *v1_ptr = v_plane;
int Y_size = width*height;
int C_size = Y_size>>1; // Every little bit helps...
unsigned char *Y_ptr = buffer;
unsigned char *Cb_ptr = buffer + Y_size;
unsigned char *Cr_ptr = Cb_ptr + C_size;
int y,u,v;
for ( int i = 0; i < Y_size; i++ )
{
*y_ptr++ = y_table[*Y_ptr++];
}
for ( int i = 0, j = 0; i < C_size; i++, j++ )
{
u = uv_table[*Cb_ptr++];
int Y_size = width*height;
int C_size = Y_size>>1; // Every little bit helps...
unsigned char *Y_ptr = buffer;
unsigned char *Cb_ptr = buffer + Y_size;
unsigned char *Cr_ptr = Cb_ptr + C_size;
int y,u,v;
for ( int i = 0; i < Y_size; i++ )
{
*y_ptr++ = y_table[*Y_ptr++];
}
for ( int i = 0, j = 0; i < C_size; i++, j++ )
{
u = uv_table[*Cb_ptr++];
*u1_ptr++ = u;
*u1_ptr++ = u;
*u1_ptr++ = u;
*u1_ptr++ = u;
v = uv_table[*Cr_ptr++];
v = uv_table[*Cr_ptr++];
*v1_ptr++ = v;
*v1_ptr++ = v;
}
*v1_ptr++ = v;
*v1_ptr++ = v;
}
y_ptr = y_plane;
u1_ptr = u_plane;
v1_ptr = v_plane;
int size = Y_size*3;
int r,g,b;
for ( int i = 0; i < size; i += 3 )
{
y = *y_ptr++;
u = *u1_ptr++;
v = *v1_ptr++;
y_ptr = y_plane;
u1_ptr = u_plane;
v1_ptr = v_plane;
int size = Y_size*3;
int r,g,b;
for ( int i = 0; i < size; i += 3 )
{
y = *y_ptr++;
u = *u1_ptr++;
v = *v1_ptr++;
r = y + r_v_table[v];
g = y - (g_u_table[u]+g_v_table[v]);
b = y + b_u_table[u];
r = y + r_v_table[v];
g = y - (g_u_table[u]+g_v_table[v]);
b = y + b_u_table[u];
*rgb_ptr++ = r<0?0:(r>255?255:r);
*rgb_ptr++ = g<0?0:(g>255?255:g);
*rgb_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_YUYV :
case VIDEO_PALETTE_YUV422 :
{
int size = width*height*2;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
*rgb_ptr++ = r<0?0:(r>255?255:r);
*rgb_ptr++ = g<0?0:(g>255?255:g);
*rgb_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_YUYV :
case VIDEO_PALETTE_YUV422 :
{
int size = width*height*2;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
int y1,y2,u,v;
int r,g,b;
for ( int i = 0; i < size; i += 4 )
{
y1 = *s_ptr++;
u = *s_ptr++;
y2 = *s_ptr++;
v = *s_ptr++;
int y1,y2,u,v;
int r,g,b;
for ( int i = 0; i < size; i += 4 )
{
y1 = *s_ptr++;
u = *s_ptr++;
y2 = *s_ptr++;
v = *s_ptr++;
r = y1 + r_v_table[v];
g = y1 - (g_u_table[u]+g_v_table[v]);
b = y1 + b_u_table[u];
r = y1 + r_v_table[v];
g = y1 - (g_u_table[u]+g_v_table[v]);
b = y1 + b_u_table[u];
*d_ptr++ = r<0?0:(r>255?255:r);
*d_ptr++ = g<0?0:(g>255?255:g);
*d_ptr++ = b<0?0:(b>255?255:b);
*d_ptr++ = r<0?0:(r>255?255:r);
*d_ptr++ = g<0?0:(g>255?255:g);
*d_ptr++ = b<0?0:(b>255?255:b);
r = y2 + r_v_table[v];
g = y2 - (g_u_table[u]+g_v_table[v]);
b = y2 + b_u_table[u];
r = y2 + r_v_table[v];
g = y2 - (g_u_table[u]+g_v_table[v]);
b = y2 + b_u_table[u];
*d_ptr++ = r<0?0:(r>255?255:r);
*d_ptr++ = g<0?0:(g>255?255:g);
*d_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB555 :
{
int size = width*height*2;
unsigned char r,g,b;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 2 )
{
b = ((*s_ptr)<<3)&0xf8;
g = (((*(s_ptr+1))<<6)|((*s_ptr)>>2))&0xf8;
r = ((*(s_ptr+1))<<1)&0xf8;
*d_ptr++ = r<0?0:(r>255?255:r);
*d_ptr++ = g<0?0:(g>255?255:g);
*d_ptr++ = b<0?0:(b>255?255:b);
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB555 :
{
int size = width*height*2;
unsigned char r,g,b;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 2 )
{
b = ((*s_ptr)<<3)&0xf8;
g = (((*(s_ptr+1))<<6)|((*s_ptr)>>2))&0xf8;
r = ((*(s_ptr+1))<<1)&0xf8;
*d_ptr++ = r;
*d_ptr++ = g;
*d_ptr++ = b;
s_ptr += 2;
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB565 :
{
int size = width*height*2;
unsigned char r,g,b;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 2 )
{
b = ((*s_ptr)<<3)&0xf8;
g = (((*(s_ptr+1))<<5)|((*s_ptr)>>3))&0xfc;
r = (*(s_ptr+1))&0xf8;
*d_ptr++ = r;
*d_ptr++ = g;
*d_ptr++ = b;
s_ptr += 2;
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB565 :
{
int size = width*height*2;
unsigned char r,g,b;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 2 )
{
b = ((*s_ptr)<<3)&0xf8;
g = (((*(s_ptr+1))<<5)|((*s_ptr)>>3))&0xfc;
r = (*(s_ptr+1))&0xf8;
*d_ptr++ = r;
*d_ptr++ = g;
*d_ptr++ = b;
s_ptr += 2;
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB24 :
{
if ( config.local_bgr_invert )
{
int size = width*height*3;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 3 )
{
*d_ptr++ = *(s_ptr+2);
*d_ptr++ = *(s_ptr+1);
*d_ptr++ = *s_ptr;
s_ptr += 3;
}
buffer = temp_buffer;
}
break;
}
case VIDEO_PALETTE_GREY :
{
//int size = width*height;
//for ( int i = 0; i < size; i++ )
//{
//if ( buffer[i] < 16 )
//Info(( "Lo grey %d", buffer[i] ));
//if ( buffer[i] > 235 )
//Info(( "Hi grey %d", buffer[i] ));
//}
}
default : // Everything else is straightforward, for now.
{
break;
}
}
*d_ptr++ = r;
*d_ptr++ = g;
*d_ptr++ = b;
s_ptr += 2;
}
buffer = temp_buffer;
break;
}
case VIDEO_PALETTE_RGB24 :
{
if ( config.local_bgr_invert )
{
int size = width*height*3;
unsigned char *s_ptr = buffer;
unsigned char *d_ptr = temp_buffer;
for ( int i = 0; i < size; i += 3 )
{
*d_ptr++ = *(s_ptr+2);
*d_ptr++ = *(s_ptr+1);
*d_ptr++ = *s_ptr;
s_ptr += 3;
}
buffer = temp_buffer;
}
break;
}
case VIDEO_PALETTE_GREY :
{
//int size = width*height;
//for ( int i = 0; i < size; i++ )
//{
//if ( buffer[i] < 16 )
//Info(( "Lo grey %d", buffer[i] ));
//if ( buffer[i] > 235 )
//Info(( "Hi grey %d", buffer[i] ));
//}
}
default : // Everything else is straightforward, for now.
{
break;
}
}
}
image.Assign( width, height, colours, buffer );

View File

@@ -37,7 +37,13 @@ protected:
int channel;
int format;
int channel_index;
protected:
static int camera_count;
static int channel_count;
static int last_channel;
static int m_cap_frame;
static int m_cap_frame_active;
static int m_sync_frame;
@@ -45,7 +51,6 @@ protected:
static video_mmap *m_vmm;
static int m_videohandle;
static unsigned char *m_buffer;
static int camera_count;
static unsigned char *y_table;
static signed char *uv_table;
static short *r_v_table;
@@ -69,6 +74,7 @@ public:
int Colour( int p_colour=-1 );
int Contrast( int p_contrast=-1 );
int PrimeCapture();
int PreCapture();
int PostCapture( Image &image );

View File

@@ -1479,11 +1479,11 @@ int Monitor::LoadLocalMonitors( const char *device, Monitor **&monitors, Purpose
static char sql[BUFSIZ];
if ( !device[0] )
{
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Local'", sizeof(sql) );
strncpy( sql, "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Local' order by Device, Channel", sizeof(sql) );
}
else
{
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Local' and Device = '%s'", device );
snprintf( sql, sizeof(sql), "select Id, Name, Function+0, Enabled, LinkedMonitors, Device, Channel, Format, Width, Height, Palette, Orientation+0, Brightness, Contrast, Hue, Colour, EventPrefix, LabelFormat, LabelX, LabelY, ImageBufferCount, WarmupCount, PreEventCount, PostEventCount, AlarmFrameCount, SectionLength, FrameSkip, MaxFPS, AlarmMaxFPS, FPSReportInterval, RefBlendPerc, TrackMotion from Monitors where Function != 'None' and Type = 'Local' and Device = '%s' order by Channel", device );
}
if ( mysql_query( &dbconn, sql ) )
{

View File

@@ -301,6 +301,10 @@ public:
int actionColour( int p_colour=-1 );
int actionContrast( int p_contrast=-1 );
inline int PrimeCapture()
{
return( camera->PrimeCapture() );
}
inline int PreCapture()
{
return( camera->PreCapture() );

View File

@@ -191,12 +191,10 @@ int main( int argc, char *argv[] )
sigaddset( &block_set, SIGUSR1 );
sigaddset( &block_set, SIGUSR2 );
if ( device[0] && n_monitors == 1 )
if ( monitors[0]->PrimeCapture() < 0 )
{
if ( monitors[0]->PreCapture() < 0 )
{
exit( -1 );
}
exit( -1 );
}
long *capture_delays = new long[n_monitors];
@@ -214,7 +212,6 @@ int main( int argc, char *argv[] )
struct DeltaTimeval delta_time;
while( !zm_terminate )
{
/* grab a new one */
sigprocmask( SIG_BLOCK, &block_set, 0 );
for ( int i = 0; i < n_monitors; i++ )
{
@@ -231,9 +228,7 @@ int main( int argc, char *argv[] )
else
next_delays[j] = capture_delays[j]-delta_time.delta;
if ( next_delays[j] < 0 )
{
next_delays[j] = 0;
}
}
else
{

View File

@@ -1032,7 +1032,8 @@ if ( !empty($action) )
if ( $cookies ) session_write_close();
if ( daemonCheck() )
{
zmcControl( $monitor );
$restart = ($old_function == 'None') || ($new_function == 'None') || ($new_enabled != $old_enabled);
zmcControl( $monitor, $restart?"restart":"" );
zmaControl( $monitor, "reload" );
}
$refresh_parent = true;

View File

@@ -319,7 +319,7 @@ foreach( $monitors as $monitor )
$zone_count += $monitor['ZoneCount'];
?>
<tr>
<td align="center" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", $monitor['Id'].'.', canView( 'Monitors' ) ) ?></td>
<td align="center" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor".$monitor['Id']."', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", $monitor['Id'].'.', canView( 'Monitors' ) ) ?></td>
<?php
if ( !$monitor['zmc'] )
{
@@ -357,11 +357,11 @@ foreach( $monitors as $monitor )
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=watch&mid=".$monitor['Id']."', 'zmWatch".$monitor['Id']."', ".(reScale( $monitor['Width'], $scale )+$jws['watch']['w']).", ".(reScale( $monitor['Height'], $scale )+$jws['watch']['h'])." );", $monitor['Name'], $running && ($monitor['Function'] != 'None') && canView( 'Stream' ) ) ?></td>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=function&mid=".$monitor['Id']."', 'zmFunction', ".$jws['function']['w'].", ".$jws['function']['h']." );", "<span class=\"$fclass\">".$monitor['Function']."</span>", canEdit( 'Monitors' ) ) ?></td>
<?php if ( $monitor['Type'] == "Local" ) { ?>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".$monitor['Device']." (".$monitor['Channel'].")</span>", canEdit( 'Monitors' ) ) ?></td>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor".$monitor['Id']."', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".$monitor['Device']." (".$monitor['Channel'].")</span>", canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "Remote" ) { ?>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".preg_replace( '/^.*@/', '', $monitor['Host'] )."</span>", canEdit( 'Monitors' ) ) ?></td>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor".$monitor['Id']."', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".preg_replace( '/^.*@/', '', $monitor['Host'] )."</span>", canEdit( 'Monitors' ) ) ?></td>
<?php } elseif ( $monitor['Type'] == "File" ) { ?>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".preg_replace( '/^.*\//', '', $monitor['Path'] )."</span>", canEdit( 'Monitors' ) ) ?></td>
<td align="left" class="text"><?= makeLink( "javascript: newWindow( '$PHP_SELF?view=monitor&mid=".$monitor['Id']."', 'zmMonitor".$monitor['Id']."', ".$jws['monitor']['w'].", ".$jws['monitor']['h']." );", "<span class=\"$dclass\">".preg_replace( '/^.*\//', '', $monitor['Path'] )."</span>", canEdit( 'Monitors' ) ) ?></td>
<?php } else { ?>
<td align="left" class="text">&nbsp;</td>
<?php } ?>
@@ -390,7 +390,7 @@ if ( canEdit('Monitors') )
<table align="center" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td align="center"><input type="button" value="<?= $zmSlangRefresh ?>" class="form" onClick="javascript: location.reload(true);"></td>
<td align="center"><input type="button" value="<?= $zmSlangAddNewMonitor ?>" class="form" onClick="javascript: newWindow( '<?= $PHP_SELF ?>?view=monitor', 'zmMonitor', <?= $jws['monitor']['w'] ?>, <?= $jws['monitor']['h'] ?>);"<?php if ( !canEdit( 'Monitors' ) || $user['MonitorIds'] ) {?> disabled<?php } ?>></td>
<td align="center"><input type="button" value="<?= $zmSlangAddNewMonitor ?>" class="form" onClick="javascript: newWindow( '<?= $PHP_SELF ?>?view=monitor', 'zmMonitor0', <?= $jws['monitor']['w'] ?>, <?= $jws['monitor']['h'] ?>);"<?php if ( !canEdit( 'Monitors' ) || $user['MonitorIds'] ) {?> disabled<?php } ?>></td>
<td align="center"><input type="button" value="<?= $zmSlangFilters ?>" class="form" onClick="javascript: scrollWindow( '<?= $PHP_SELF ?>?view=events&page=1&filter=1&trms=1&attr1=DateTime&op1=%3c&val1=now', 'zmEvents', <?= $jws['events']['w'] ?>, <?= $jws['events']['h'] ?> );"<?php if ( !canView( 'Events' ) ) {?> disabled<?php } ?>></td>
</tr>
</table>