Index: src/zm_image.cpp
===================================================================
--- src/zm_image.cpp	(revision 2859)
+++ src/zm_image.cpp	(working copy)
@@ -295,7 +295,7 @@
 		return( false );
 	}
 
-	if ( fwrite( buffer, size, 1, outfile ) < 1 )
+	if ( fwrite( buffer, size, 1, outfile ) != 1 )
     {
         Error( "Unable to write to '%s': %s", filename, strerror(errno) );
         return( false );
Index: src/zm_event.cpp
===================================================================
--- src/zm_event.cpp	(revision 2859)
+++ src/zm_event.cpp	(working copy)
@@ -1235,7 +1235,7 @@
                 break;
         }
         fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size );
-        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 )
+        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 )
         {
             Error( "Unable to send stream frame: %s", strerror(errno) );
             return( false );
Index: src/zm_monitor.cpp
===================================================================
--- src/zm_monitor.cpp	(revision 2859)
+++ src/zm_monitor.cpp	(working copy)
@@ -3231,7 +3231,7 @@
         fprintf( stdout, "--ZoneMinderFrame\r\n" );
         fprintf( stdout, "Content-Length: %d\r\n", img_buffer_size );
         fprintf( stdout, "Content-Type: image/jpeg\r\n\r\n" );
-        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 )
+        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 )
         {
             Error( "Unable to send stream frame: %s", strerror(errno) );
             return( false );
@@ -3316,7 +3316,7 @@
                 break;
         }
         fprintf( stdout, "Content-Length: %d\r\n\r\n", img_buffer_size );
-        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) < 0 )
+        if ( fwrite( img_buffer, img_buffer_size, 1, stdout ) != 1 )
         {
             Error( "Unable to send stream frame: %s", strerror(errno) );
             return( false );
@@ -3401,7 +3401,7 @@
             Debug( 2, "Assigned temporary buffer" );
         }
     }
-
+	float max_secs_since_last_sent_frame = 10; //should be > keep alive amount (5 secs)
 	while ( !zm_terminate )
 	{
         bool got_command = false;
@@ -3575,6 +3575,12 @@
                 break;
             }
         }
+		if (TV_2_FLOAT( now ) - last_frame_sent > max_secs_since_last_sent_frame)
+		{
+
+			Error( "Killing myself off as have exceeded max_secs_since_last_sent_frame of %f (max %f)", TV_2_FLOAT( now ) - last_frame_sent, max_secs_since_last_sent_frame );
+			break;
+		}
 	}
     if ( buffered_playback )
     {
Index: web/ajax/stream.php
===================================================================
--- web/ajax/stream.php	(revision 2859)
+++ web/ajax/stream.php	(working copy)
@@ -46,6 +46,11 @@
 }
 
 $remSockFile = ZM_PATH_SOCKS.'/zms-'.sprintf("%06d",$_REQUEST['connkey']).'s.sock';
+$max_socket_tries = 3;
+while (!  file_exists($remSockFile) && $max_socket_tries-- ) //sometimes we are too fast for our own good, if it hasn't been setup yet give it a second.
+	sleep(1);
+
+
 if ( !@socket_sendto( $socket, $msg, strlen($msg), 0, $remSockFile ) )
 {
     ajaxError( "socket_sendto( $remSockFile ) failed: ".socket_strerror(socket_last_error()) );
Index: web/skins/classic/js/skin.js
===================================================================
--- web/skins/classic/js/skin.js	(revision 2859)
+++ web/skins/classic/js/skin.js	(working copy)
@@ -24,7 +24,7 @@
 
 if ( !window.console )
 {
-    var console =
+    window.console =
     {
         init:function() {},
         log:function() {},
@@ -34,6 +34,8 @@
         error:function() {}
     };
 }
+if (! console.debug)//IE8 has console but doesn't have console.debug so lets alias it.
+	console.debug = console.log;
 
 // Javascript window sizes
 var popupSizes = {
@@ -219,7 +221,17 @@
     if ( window.opener )
         window.opener.location.reload( true );
 }
-
+function checkStreamForErrors(funcName,streamObj){ //Shows a message if there is an error in the streamObj or the stream doesn't exist.  Returns true if error, false otherwise.
+	if (! streamObj){
+		console.error(funcName + ": stream object was null");
+		return true;
+	}
+	if (streamObj.result == "Error"){
+		console.error(funcName + " stream error: " + streamObj.message);
+		return true;
+	}
+	return false;
+}
 function secsToTime( seconds )
 {
     var timeString = "--";
Index: web/skins/classic/views/js/watch.js
===================================================================
--- web/skins/classic/views/js/watch.js	(revision 2859)
+++ web/skins/classic/views/js/watch.js	(working copy)
@@ -35,10 +35,11 @@
     // This causes FF3 to kill the stream now, ok with FF2
     //streamCmdScale( scale );
 
-    var streamImg = $('imageFeed').getElement('img');
-    if ( !streamImg )
-        streamImg = $('imageFeed').getElement('object');
-    streamImg.setStyles( { width: newWidth, height: newHeight } );
+	/*Stream could be an applet so can't use moo tools*/ 
+    var streamImg = document.getElementById('liveStream');
+	streamImg.style.width = newWidth + "px";
+	streamImg.style.height = newHeight + "px";
+
 }
 
 var alarmState = STATE_IDLE;
Index: web/skins/classic/views/js/montage.js.php
===================================================================
--- web/skins/classic/views/js/montage.js.php	(revision 2859)
+++ web/skins/classic/views/js/montage.js.php	(working copy)
@@ -31,7 +31,7 @@
 foreach ( $monitors as $monitor )
 {
 ?>
-monitorData[monitorData.length] = { 'id': <?= $monitor['Id'] ?>, 'connKey': <?= $monitor['connKey'] ?> };
+monitorData[monitorData.length] = { 'id': <?= $monitor['Id'] ?>, 'connKey': <?= $monitor['connKey'] ?>, 'width': <?= $monitor['Width'] ?>,'height':<?= $monitor['Height'] ?> };
 <?php
 }
 ?>
Index: web/skins/classic/views/js/montage.js
===================================================================
--- web/skins/classic/views/js/montage.js	(revision 2859)
+++ web/skins/classic/views/js/montage.js	(working copy)
@@ -38,10 +38,9 @@
                 $('monitorState'+this.index).setProperty( 'class', stateClass );
             }
             $('monitor'+this.index).setProperty( 'class', stateClass );
-            var stream = $('imageFeed'+this.index).getElement( 'img' );
-            if ( !stream )
-                stream = $('imageFeed'+this.index).getElement( 'object' );
-            stream.setProperty( 'class', stateClass );
+			/*Stream could be an applet so can't use moo tools*/ 
+            var stream = document.getElementById("liveStream" + this.id );
+            stream.className=stateClass;
 
             var isAlarmed = ( this.alarmState == STATE_ALARM || this.alarmState == STATE_ALERT );
             var wasAlarmed = ( this.lastAlarmState == STATE_ALARM || this.lastAlarmState == STATE_ALERT );
@@ -98,7 +97,25 @@
     new Asset.css( cssFile, { id: 'dynamicStyles' } );
     Cookie.write( 'zmMontageLayout', $(element).get('value'), { duration: 10*365 } );
 }
+function changeScale()
+{
+    var scale = $('scale').get('value');
 
+
+
+	for (x = 0; x < monitors.length;x++)
+	{
+		var monitor = monitors[x];
+	    var newWidth = ( monitorData[x].width * scale ) / SCALE_BASE;
+	    var newHeight = ( monitorData[x].height * scale ) / SCALE_BASE;
+	/*Stream could be an applet so can't use moo tools*/ 
+	    var streamImg = document.getElementById('liveStream' + monitor.id);
+		streamImg.style.width = newWidth + "px";
+		streamImg.style.height = newHeight + "px";
+	}
+}
+
+
 var monitors = new Array();
 function initPage()
 {
Index: web/skins/classic/views/js/event.js
===================================================================
--- web/skins/classic/views/js/event.js	(revision 2859)
+++ web/skins/classic/views/js/event.js	(working copy)
@@ -14,8 +14,10 @@
 
     streamScale( scale );
 
-    var streamImg = $('imageFeed').getElement('img');
-    $(streamImg).setStyles( { 'width': newWidth, 'height': newHeight } );
+	/*Stream could be an applet so can't use moo tools*/ 
+    var streamImg = document.getElementById('evtStream');
+	streamImg.style.width = newWidth + "px";
+	streamImg.style.height = newHeight + "px";
 }
 
 function changeReplayMode()
@@ -35,6 +37,9 @@
 
 function getCmdResponse( respObj, respText )
 {
+	if ( checkStreamForErrors("getCmdResponse",respObj) )
+		return;
+
     if ( streamCmdTimer )
         streamCmdTimer = $clear( streamCmdTimer );
 
@@ -89,7 +94,8 @@
 function streamPlay( action )
 {
     setButtonState( $('pauseBtn'), 'inactive' );
-    setButtonState( $('playBtn'), streamStatus.rate==1?'active':'inactive' );
+	if (streamStatus)
+	    setButtonState( $('playBtn'), streamStatus.rate==1?'active':'inactive' );
     setButtonState( $('fastFwdBtn'), 'inactive' );
     setButtonState( $('slowFwdBtn'), 'unavail' );
     setButtonState( $('slowRevBtn'), 'unavail' );
@@ -226,6 +232,9 @@
 
 function getEventResponse( respObj, respText )
 {
+	if ( checkStreamForErrors("getEventResponse",respObj) )
+		return;
+
     event = respObj.event;
     if ( !$('eventStills').hasClass( 'hidden' ) && currEventId != event.Id )
         resetEventStills();
@@ -275,6 +284,8 @@
 
 function getNearEventsResponse( respObj, respText )
 {
+	if ( checkStreamForErrors("getNearEventsResponse",respObj) )
+		return;
     prevEventId = respObj.nearevents.PrevEventId;
     nextEventId = respObj.nearevents.NextEventId;
 
@@ -316,7 +327,7 @@
     );
 }
 
-function updateStillsSizes()
+function updateStillsSizes(noDelay)
 {
     var containerDim = $('eventThumbs').getStyles( 'width', 'height' );
     var popupDim = $('eventImageFrame').getStyles( 'width', 'height' );
@@ -332,7 +343,11 @@
     if ( left < 0 ) left = 0;
     var top = (containerHeight - popupHeight)/2;
     if ( top < 0 ) top = 0;
-
+	if (popupHeight == 0 && ! noDelay) // image not yet loaded lets give it another second
+	{
+		setTimeout(updateStillsSizes.bind(this,true),50);
+		return;
+	}
     $('eventImagePanel').setStyles( {
         'left': left,
         'top': top
@@ -412,6 +427,8 @@
             steps: event.Frames,
             onChange: function( step )
             {
+				if (! step)
+					step = 0;
                 var fid = step + 1;
                 checkFrames( event.Id, fid );
                 scroll.toElement( 'eventThumb'+fid );
@@ -426,6 +443,9 @@
 
 function getFrameResponse( respObj, respText )
 {
+	if ( checkStreamForErrors("getFrameResponse",respObj) )
+		return;
+
     var frame = respObj.frameimage;
 
     if ( !event )
@@ -508,7 +528,7 @@
         {
             if ( loadImage && (fid == frameId) )
             {
-                loadEventImage( event, event['frames'][fid] );
+                loadEventImage( event, event['frames'][fid], loadImage );
             }
         }
     }
@@ -567,6 +587,9 @@
 
 function getActResponse( respObj, respText )
 {
+	if ( checkStreamForErrors("getActResponse",respObj) )
+		return;
+
     if ( respObj.refreshParent )
         refreshParentWindow();
 
Index: web/skins/classic/views/montage.php
===================================================================
--- web/skins/classic/views/montage.php	(revision 2859)
+++ web/skins/classic/views/montage.php	(working copy)
@@ -44,8 +44,13 @@
     {
         continue;
     }
-    $scaleWidth = reScale( $row['Width'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
-    $scaleHeight = reScale( $row['Height'], $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
+	if ( isset( $_REQUEST['scale'] ) )
+		$scale = validInt($_REQUEST['scale']);
+	else
+		$scale = reScale( SCALE_BASE, $row['DefaultScale'], ZM_WEB_DEFAULT_SCALE );
+
+    $scaleWidth = reScale( $row['Width'], $scale );
+    $scaleHeight = reScale( $row['Height'], $scale );
     if ( $maxWidth < $scaleWidth )
         $maxWidth = $scaleWidth;
     if ( $maxHeight < $scaleHeight )
@@ -90,7 +95,8 @@
       </div>
       <h2><?= $SLANG['Montage'] ?></h2>
       <div id="headerControl">
-        <label for="layout"><?= $SLANG['Layout'] ?></label><?= buildSelect( "layout", $layouts, 'selectLayout( this )' )?>
+	  	  <span id="scaleControl"><?= $SLANG['Scale'] ?>: <?= buildSelect( "scale", $scales, "changeScale( this );" ); ?></span> 
+        <label for="layout"><?= $SLANG['Layout'] ?>:</label><?= buildSelect( "layout", $layouts, 'selectLayout( this )' )?>
       </div>
     </div>
     <div id="content">
Index: web/skins/classic/views/css/event.css
===================================================================
--- web/skins/classic/views/css/event.css	(revision 2859)
+++ web/skins/classic/views/css/event.css	(working copy)
@@ -161,6 +161,7 @@
 
 #eventThumbs img {
     height: 80px;
+	width: 107px;
     margin: 2px;
     background-color: #dddddd;
 }
Index: web/skins/mobile/views/console.php
===================================================================
--- web/skins/mobile/views/console.php	(revision 2859)
+++ web/skins/mobile/views/console.php	(working copy)
@@ -86,7 +86,7 @@
 <body>
   <div id="page">
     <div id="header">
-      <div id="systemTime"><a href="?view=<?= $_REQUEST['view'] ?>"><?= preg_match( '/%/', DATE_FMT_CONSOLE_SHORT )?strftime( DATE_FMT_CONSOLE_SHORT ):date( DATE_FMT_CONSOLE_SHORT ) ?></a></div>
+      <div id="systemTime"><a href="?view=$view"><?= preg_match( '/%/', DATE_FMT_CONSOLE_SHORT )?strftime( DATE_FMT_CONSOLE_SHORT ):date( DATE_FMT_CONSOLE_SHORT ) ?></a></div>
       <div id="systemStats"><?= getLoad() ?>/<?= getDiskPercent() ?>%</div>
       <div id="systemState"><?= makeLink( "?view=state", $status, canEdit( 'System' ) ) ?></div>
     </div>
