flash : finish external interface and enhance filename.
authorcavaliet
Wed, 06 Jun 2012 15:53:30 +0200
changeset 9 4763bcd087a2
parent 8 84aba7419b17
child 10 84fc62839751
child 11 6cab7e0b1678
flash : finish external interface and enhance filename.
script/record_mic/record_mic.as
script/record_mic/record_mic.swf
script/record_mic/record_mic_example.html
--- a/script/record_mic/record_mic.as	Tue Jun 05 13:51:02 2012 +0200
+++ b/script/record_mic/record_mic.as	Wed Jun 06 15:53:30 2012 +0200
@@ -1,1 +1,1 @@
-package  {
	
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.AsyncErrorEvent;
	import flash.events.ErrorEvent;
	import flash.events.ActivityEvent;
	import flash.events.Event;
	//import flash.events.TimerEvent;
	
	import flash.media.Microphone;
	
	import flash.net.NetConnection;
	import flash.net.NetStream;
	
	import flash.system.Security;
	
	import flash.text.TextField;
	
	//import flash.utils.Timer;
	
	import fl.controls.ProgressBar;
	import fl.controls.ProgressBarMode;
	import fl.controls.Slider;
	import fl.events.SliderEvent;
	import flash.utils.setInterval;
	
	public class record_mic extends MovieClip {
		
		private var t:TextField;
		private var r:SimpleButton;
		private var p:Sprite;
		
		private var urlServer:String = "rtmp://media.iri.centrepompidou.fr/ddc_micro_record";
		private var nc:NetConnection;
		private var ns:NetStream;
		private var ns2:NetStream;
		private var mic:Microphone;
		private var filename:String;
		private var recordRunning:Boolean = false;
		private var recordStopped:Boolean = false;
		
		// Draw mic feedback
		private var pb:ProgressBar;
		private var activityCurve:Sprite;
		private var micGain:Slider;
		// Variables for the activity curve
		private var xInc:int = 0;
		private var xSpeed:int = 2;
		private var activityWidth:Number;
		// Intervals used to draw the curve et keep track of the duration of the recording
		private var drawCurve:Number;
		private var timecodeInterval:Number;
		private var timecode:Number = 0;
		
		
		public function record_mic() {
			// constructor code
			Security.allowDomain("*");
			Security.allowInsecureDomain("*");
			
			//t = _t;
			r = _recordBtn;
			p = _playBtn;
			pb = _pb;
			activityWidth = _act.width;
			activityCurve = _act._activityCurve;
			micGain = _micGain;
			trace("t = " + t + ", r = " + r + ", p = " + p + ", pb = " + pb);
			
			micGain.visible = p.visible = pb.visible = _act.visible = false;
			//r.buttonMode = r.useHandCursor = 
			p.buttonMode = p.useHandCursor = true;
			pb.mode = ProgressBarMode.MANUAL;
			r.addEventListener(MouseEvent.CLICK, startRecord);
			p.addEventListener(MouseEvent.CLICK, playRecord);
		}
		private function startRecord(e:MouseEvent=null):void{
			trace("startRecord nc = " + nc + ", recordRunning = " + recordRunning);
			if(!recordRunning){
				if (nc==null){
					trace("  startRecord 2");
					nc = new NetConnection();
					nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
					nc.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
					nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler, false, 0, true);
					nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler, false, 0, true);    	
					nc.connect(urlServer);
				}
				else{
					publish();
				}
			}
			else{
				// If record is running, we stop it
				stopRecord();
			}
		}
		private function errorHandler(e:*=null):void {
			trace("errorHandler");
        	closeStream();
        }
		private function closeStream():void{
			trace("closeStream");
			if(ns!=null){
				trace("  ns.close()");
        		ns.close();
        		ns = null;
			}
		}
		private function netStatusHandler(event:NetStatusEvent):void {
			trace("netStatusHandler : " + event.info.code);
        	switch (event.info.code) {
	        	case 'NetConnection.Connect.Success':
					publish();
	        		break;
	        	case 'NetConnection.Connect.Failed':
	        	case 'NetConnection.Connect.Reject':
	        	case 'NetConnection.Connect.Closed':
	        		//closeStream();
	        		break;
        	}
        }
		// send data over rtmp
		private function publish():void {
			trace("publish (ns==null && nc!=null && nc.connected) = " + (ns==null && nc!=null && nc.connected));
			if(nc!=null && nc.connected) {
				trace("  publish 2");
				ns = new NetStream(nc);
				ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
				ns.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
				ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler, false, 0, true);
				// informs the server to record what it receives
				// in fact file name is passed as the user name (the server is meant to record everything it has to in a file named from the user name)	
				filename = "r_" + now();
				trace("filename = " + filename);
				recordRunning = true;
				ns.publish(filename, 'record');
				mic = Microphone.getMicrophone(-1);
				mic.rate = 22;
				micGain.minimum = 0;
				micGain.maximum = 100;
				micGain.value = mic.gain = 50;
				micGain.addEventListener(SliderEvent.CHANGE, onSliderChange);
				mic.addEventListener(ActivityEvent.ACTIVITY, runMicActivity);
				mic.setUseEchoSuppression(true);
				ns.attachAudio(mic);
				micGain.visible = p.visible = pb.visible = _act.visible = true;
			}
		}
		// stop the recording of audio to the stream
		private function stopRecord(e:*=null):void{
			trace("stopRecord (ns!=null) = " + (ns!=null));
			if(ns!=null){
				trace("  stopRecord 2");
				recordRunning = false;
				recordStopped = true;
				ns.play(false); // flushes the recording buffer
    			ns.close();
			}
		}
		// plays back the audio that was recorded
		private function playRecord(e:*=null):void{
			trace("playRecord (ns!=null && recordStopped) = " + (ns!=null && recordStopped));
			if(recordStopped){
				trace("  playRecord 2");
				ns2 = new NetStream(nc);
				ns2.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler2, false, 0, true);
				ns2.addEventListener(IOErrorEvent.IO_ERROR, errorHandler2, false, 0, true);
				ns2.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler2, false, 0, true);
				ns2.play(filename);
			}
		}
		private function netStatusHandler2(event:NetStatusEvent):void {
			trace("netStatusHandler 2 : " + event.info.code);
        }
		private function errorHandler2(e:*=null):void {
			trace("errorHandler 2");
        	closeStream2();
        }
		private function closeStream2():void{
			trace("closeStream 2");
			/*if(ns2!=null){
				trace("  ns.close()");
        		ns2.close();
        		ns2 = null;
			}*/
		}
		// Now in string
		private function now():String{
			var d:Date = new Date();
			var m:uint = d.month + 1; // because Date.month begins at 0
			return d.fullYear + (m<10?("0"+m):m) + (d.date<10?("0"+d.date):d.date) + (d.hours<10?("0"+d.hours):d.hours) + (d.minutes<10?("0"+d.minutes):d.minutes) + (d.seconds<10?("0"+d.seconds):d.seconds);
		}
		
		// sets the module ready to record mic activity changes
		private function runMicActivity(e:ActivityEvent):void {
			trace("runMicActivity");
			mic.removeEventListener(ActivityEvent.ACTIVITY, runMicActivity);
			addEventListener(Event.ENTER_FRAME, showMicActivity);
			// Start activity curve feedback, every second
			activityCurve.graphics.clear();
			activityCurve.graphics.lineStyle(1, 0xc4c4c4, 1);
			activityCurve.graphics.moveTo(0, 20);
			activityCurve.graphics.beginFill(0xc4c4c4, 100);
			xInc = 0;
			activityCurve.x = 1;
			setInterval(drawSoundCurve, 100);
			/*var tmr:Timer = new Timer(1000, 1000);
			tmr.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
			tmr.addEventListener(TimerEvent.TIMER, drawSoundCurve);
			tmr.start();*/
		}
		// updates the progress bar relating to mic activity
		private function showMicActivity(e:Event):void {
			//trace("showMicActivity res = " + (mic.activityLevel*mic.gain/100));
			//pb.setProgress(mic.activityLevel*mic.gain/100 ,100);
			pb.setProgress(mic.activityLevel,100);
		}
		// updates the actiity curve relating to mic activity
		private function drawSoundCurve():void {
			if(recordRunning){
				trace("drawSoundCurve recordRunning = " + recordRunning + ", mic.activityLevel =  " + mic.activityLevel + ", mic.gain = " + mic.gain + ", h = " + (19*mic.activityLevel/100));
				activityCurve.graphics.lineTo(xInc, 19 - (19*mic.activityLevel/100));	
				activityCurve.graphics.lineTo(xInc, 19);
				if(xInc>activityWidth){
					activityCurve.x -= xSpeed;
				}
				xInc += xSpeed;
			}
		}
		// Updates mic gain
		private function onSliderChange(e:SliderEvent):void {
			trace("onSliderChange");
			mic.gain = micGain.value;
		}
		
	}
	
}
\ No newline at end of file
+package  {
	
	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.events.SecurityErrorEvent;
	import flash.events.AsyncErrorEvent;
	import flash.events.ErrorEvent;
	import flash.events.ActivityEvent;
	import flash.events.Event;
	
	import flash.media.Microphone;
	
	import flash.net.NetConnection;
	import flash.net.NetStream;
	
	import flash.system.Security;
	
	import flash.text.TextField;
	
	import fl.controls.ProgressBar;
	import fl.controls.ProgressBarMode;
	import fl.controls.Slider;
	import fl.events.SliderEvent;
	import flash.utils.setInterval;
	import flash.external.ExternalInterface;
	
	public class record_mic extends MovieClip {
		
		private var t:TextField;
		private var r:SimpleButton;
		private var p:Sprite;
		private var playVisible:Boolean = false;
		
		private var urlServer:String = "rtmp://media.iri.centrepompidou.fr/ddc_micro_record";
		private var nc:NetConnection;
		private var ns:NetStream;
		private var ns2:NetStream;
		private var mic:Microphone;
		private var filename:String;
		private var recordRunning:Boolean = false;
		private var recordStopped:Boolean = false;
		
		// Draw mic feedback
		private var pb:ProgressBar;
		private var activityCurve:Sprite;
		private var micGain:Slider;
		// Variables for the activity curve
		private var xInc:int = 0;
		private var xSpeed:int = 2;
		private var activityWidth:Number;
		// Intervals used to draw the curve et keep track of the duration of the recording
		private var drawCurve:Number;
		private var timecodeInterval:Number;
		private var timecode:Number = 0;
		
		
		public function record_mic() {
			// constructor code
			Security.allowDomain("*");
			Security.allowInsecureDomain("*");
			
			//t = _t;
			r = _recordBtn;
			p = _playBtn;
			pb = _pb;
			activityWidth = _act.width;
			activityCurve = _act._activityCurve;
			micGain = _micGain;
			trace("t = " + t + ", r = " + r + ", p = " + p + ", pb = " + pb);
			
			// Fuck CS5 "new feature from built-in preloader" : loaderInfo.parameters is from parent.parent.loaderInfo.parameter
			var flashVars:Object = new Object();
			if(parent!=null){
				if (parent.parent!=null) flashVars = parent.parent.loaderInfo.parameters;
				else flashVars = parent.loaderInfo.parameters;
			}
			else flashVars = loaderInfo.parameters;
			for(var param:Object in flashVars){
				trace("    flashVars " + param + " : " + flashVars[param.toString()]);
			}
			if(flashVars["playVisible"]=="true"){
				playVisible = true;
			}
			
			micGain.visible = p.visible = pb.visible = _act.visible = false;
			//r.buttonMode = r.useHandCursor = 
			p.buttonMode = p.useHandCursor = true;
			pb.mode = ProgressBarMode.MANUAL;
			r.addEventListener(MouseEvent.CLICK, startRecord);
			p.addEventListener(MouseEvent.CLICK, playRecord);
			
			try{
				ExternalInterface.addCallback("stopRecord", stopRecord);
			}
			catch(e:*){
				//t.text = "ExternalInterface error catch e = " + e;
			}
		}
		private function startRecord(e:MouseEvent=null):void{
			trace("startRecord nc = " + nc + ", recordRunning = " + recordRunning);
			if(!recordRunning){
				if (nc==null){
					trace("  startRecord 2");
					nc = new NetConnection();
					nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
					nc.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
					nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler, false, 0, true);
					nc.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler, false, 0, true);    	
					nc.connect(urlServer);
				}
				else{
					publish();
				}
			}
			else{
				// If record is running, we stop it
				stopRecord();
			}
		}
		private function errorHandler(e:*=null):void {
			trace("errorHandler");
        	closeStream();
        }
		private function closeStream():void{
			trace("closeStream");
			if(ns!=null){
				trace("  ns.close()");
        		ns.close();
        		ns = null;
			}
		}
		private function netStatusHandler(event:NetStatusEvent):void {
			trace("netStatusHandler : " + event.info.code);
        	switch (event.info.code) {
	        	case 'NetConnection.Connect.Success':
					publish();
	        		break;
	        	case 'NetConnection.Connect.Failed':
	        	case 'NetConnection.Connect.Reject':
	        	case 'NetConnection.Connect.Closed':
	        		//closeStream();
	        		break;
        	}
        }
		// send data over rtmp
		private function publish():void {
			trace("publish (ns==null && nc!=null && nc.connected) = " + (ns==null && nc!=null && nc.connected));
			if(nc!=null && nc.connected) {
				trace("  publish 2");
				ns = new NetStream(nc);
				ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
				ns.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
				ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler, false, 0, true);
				// informs the server to record what it receives
				// in fact file name is passed as the user name (the server is meant to record everything it has to in a file named from the user name)	
				filename = "r_" + now();
				trace("filename = " + filename);
				recordRunning = true;
				ns.publish(filename, 'record');
				mic = Microphone.getMicrophone(-1);
				mic.rate = 22;
				micGain.minimum = 0;
				micGain.maximum = 100;
				micGain.value = mic.gain = 50;
				micGain.addEventListener(SliderEvent.CHANGE, onSliderChange);
				mic.addEventListener(ActivityEvent.ACTIVITY, runMicActivity);
				mic.setUseEchoSuppression(true);
				ns.attachAudio(mic);
				micGain.visible = pb.visible = _act.visible = true;
				p.visible = playVisible;
				// ExternalInterface call to give audio url
				ExternalInterface.call("setAudioUrl", urlServer + "/" + filename);
			}
		}
		// stop the recording of audio to the stream
		private function stopRecord(e:*=null):void{
			trace("stopRecord (ns!=null) = " + (ns!=null));
			if(ns!=null){
				trace("  stopRecord 2");
				recordRunning = false;
				recordStopped = true;
				ns.play(false); // flushes the recording buffer
    			ns.close();
			}
		}
		// plays back the audio that was recorded
		private function playRecord(e:*=null):void{
			trace("playRecord (ns!=null && recordStopped) = " + (ns!=null && recordStopped));
			if(recordStopped){
				trace("  playRecord 2");
				ns2 = new NetStream(nc);
				ns2.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler2, false, 0, true);
				ns2.addEventListener(IOErrorEvent.IO_ERROR, errorHandler2, false, 0, true);
				ns2.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler2, false, 0, true);
				ns2.play(filename);
			}
		}
		private function netStatusHandler2(event:NetStatusEvent):void {
			trace("netStatusHandler 2 : " + event.info.code);
        }
		private function errorHandler2(e:*=null):void {
			trace("errorHandler 2");
        	closeStream2();
        }
		private function closeStream2():void{
			trace("closeStream 2");
			/*if(ns2!=null){
				trace("  ns.close()");
        		ns2.close();
        		ns2 = null;
			}*/
		}
		// Now in string
		private function now():String{
			var d:Date = new Date();
			var m:uint = d.month + 1; // because Date.month begins at 0
			return d.fullYear + (m<10?("0"+m):m) + (d.date<10?("0"+d.date):d.date) + (d.hours<10?("0"+d.hours):d.hours) + (d.minutes<10?("0"+d.minutes):d.minutes) + (d.seconds<10?("0"+d.seconds):d.seconds) + (d.milliseconds<100?"0":"") + (d.milliseconds<10?"0":"") + d.milliseconds;
		}
		
		// sets the module ready to record mic activity changes
		private function runMicActivity(e:ActivityEvent):void {
			trace("runMicActivity");
			mic.removeEventListener(ActivityEvent.ACTIVITY, runMicActivity);
			addEventListener(Event.ENTER_FRAME, showMicActivity);
			// Start activity curve feedback, every second
			activityCurve.graphics.clear();
			activityCurve.graphics.lineStyle(1, 0xc4c4c4, 1);
			activityCurve.graphics.moveTo(0, 20);
			activityCurve.graphics.beginFill(0xc4c4c4, 100);
			xInc = 0;
			activityCurve.x = 1;
			setInterval(drawSoundCurve, 100);
		}
		// updates the progress bar relating to mic activity
		private function showMicActivity(e:Event):void {
			//trace("showMicActivity res = " + mic.activityLevel);
			pb.setProgress(mic.activityLevel,100);
		}
		// updates the actiity curve relating to mic activity
		private function drawSoundCurve():void {
			if(recordRunning){
				trace("drawSoundCurve recordRunning = " + recordRunning + ", mic.activityLevel =  " + mic.activityLevel + ", mic.gain = " + mic.gain + ", h = " + (19*mic.activityLevel/100));
				activityCurve.graphics.lineTo(xInc, 19 - (19*mic.activityLevel/100));	
				activityCurve.graphics.lineTo(xInc, 19);
				if(xInc>activityWidth){
					activityCurve.x -= xSpeed;
				}
				xInc += xSpeed;
			}
		}
		// Updates mic gain
		private function onSliderChange(e:SliderEvent):void {
			trace("onSliderChange");
			mic.gain = micGain.value;
		}
		
	}
	
}
\ No newline at end of file
Binary file script/record_mic/record_mic.swf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/script/record_mic/record_mic_example.html	Wed Jun 06 15:53:30 2012 +0200
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" lang="fr" xml:lang="fr">
+	<head>
+		<title>record_mic</title>
+		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+		<style type="text/css" media="screen">
+		html, body { height:100%; background-color: #AAAAAA;}
+		body { margin:0; padding:0; overflow:hidden; }
+		#flashContent { width:220px; height:140px; }
+		</style>
+	    <script type="text/javascript">
+// External callback function
+function setAudioUrl(u){
+    console.log("setAudioUrl u = " + u);
+}
+// External interface function
+function recorder_stopRecord(){
+    player_p = document.getElementById("record_mic");
+    player   = player_p.getElementsByTagName("embed")[0];
+    if (player){
+        player.stopRecord();
+        //output_send('call method: playVideo()');
+    }
+}
+	    </script>
+	</head>
+	<body>
+		<div id="flashContent">
+			<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="220" height="140" id="record_mic" align="middle">
+                <param name="movie" value="record_mic.swf" />
+                <param name="quality" value="high" />
+                <param name="bgcolor" value="#ffffff" />
+                <param name="play" value="true" />
+                <param name="loop" value="true" />
+                <param name="wmode" value="transparent" />
+                <param name="scale" value="showall" />
+                <param name="menu" value="true" />
+                <param name="devicefont" value="false" />
+                <param name="salign" value="" />
+                <param name="allowScriptAccess" value="always" />
+                <param name="allowFullScreen" value="true" />
+                <param name="flashvars" value="playVisible=true">
+                <embed src="record_mic.swf" quality="high" bgcolor="#ffffff"
+                     width="220" height="140" name="ExternalInterfaceExample" align="middle"
+                     play="true" loop="false" quality="high" allowScriptAccess="always" 
+                     type="application/x-shockwave-flash" allowFullScreen="true" wmode="transparent" 
+                     flashvars="playVisible=true"
+                     pluginspage="http://www.macromedia.com/go/getflashplayer">
+                </embed>
+            </object>
+			
+		</div>
+		<input type="button" class="button" onclick="javascript:recorder_stopRecord();" value="stopRecord" />
+	</body>
+</html>