Receiving a stream of a NetGroup - actionscript-3

I'm trying to receive a stream of a NetGroup (television) but it fails at some point. Here is the code (reduced to a testcase):
package lib
{
import flash.events.NetStatusEvent;
import flash.external.ExternalInterface;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.GroupSpecifier;
import flash.net.NetConnection;
import flash.net.NetGroup;
import flash.net.NetStream;
import flash.net.NetStreamPlayOptions;
import mx.core.FlexGlobals;
public class player
{
private var connection:NetConnection;
private var group:NetGroup;
private var group_option:GroupSpecifier;
private var self:Object;
private var stream:NetStream;
private var stream_option:NetStreamPlayOptions;
private var video:Video;
private function _connect():void
{
self.connection = new NetConnection();
self.connection.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
self.connection.connect('rtmfp://p2p.peer-stream.com');
}
private function _event_net_status(event:NetStatusEvent):void
{
if(event.info.code === '')
return;
ExternalInterface.call('echo', 'status', event.info.code, false);
switch(event.info.code)
{
case 'NetConnection.Connect.Success':
self._p2p_start();
break;
case 'NetGroup.Connect.Success':
self._stream_init();
break;
case 'NetStream.Connect.Success':
self._stream_start();
break;
}
}
private function _p2p_start():void
{
self.group_option = new GroupSpecifier('G:0101010c0b0e70726f2073696562656e00');
self.group_option.ipMulticastMemberUpdatesEnabled = true;
self.group_option.multicastEnabled = true;
self.group_option.objectReplicationEnabled = true;
self.group_option.postingEnabled = true;
self.group_option.routingEnabled = true;
self.group_option.serverChannelEnabled = true;
self.group = new NetGroup(self.connection, self.group_option.groupspecWithAuthorizations());
self.group.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_init():void
{
self.stream = new NetStream(self.connection, self.group_option.groupspecWithAuthorizations());
self.stream.addEventListener(NetStatusEvent.NET_STATUS, self._event_net_status);
}
private function _stream_start():void
{
self.video.attachNetStream(self.stream);
self.stream.soundTransform = new SoundTransform();
self.stream_option = new NetStreamPlayOptions();
self.stream_option.streamName = 'G:0101010c0b0e70726f2073696562656e00';
self.stream.play2(self.stream_option);
}
public function player():void
{
super();
FlexGlobals.topLevelApplication.stage.quality = 'BEST';
self = this;
self.video = new Video(640, 480);
FlexGlobals.topLevelApplication.video_box.addChild(self.video);
self.video.smoothing = true;
self._connect();
}
}
}
The ExternalInterface call there shows me just the passed info in a textfield (I'm testing this in a browser). Here is the result of this output:
NetConnection.Connect.Success
NetGroup.Connect.Success
NetStream.Connect.Success
NetStream.Play.Reset
NetStream.Play.Start
But nothing happens on the player. Here are my thoughts:
I'm using the same string as GroupSpecifier and streamName but I'm assuming this is wrong. If so how can I get the stream name of the NetGroup?
I'm enabling everything from the GroupSpecifier as I don't know what are the minimum requirements to receive a stream and pass it then to another clients. Maybe enabling all makes some troubles here.
Maybe somebody can tell me how I can solve this problem to finally see a stream.

I was able to solve the problem: The streamName was indeed wrong and I could manually figure out the correct name. Also instead of using new GroupSpecifier() I must pass the known group-string directly to the NetGroup and NetStream object.

Related

How to create local multiplayer functionality in AIR for mobile

I am working on a multiplayer game in AS3/AIR for mobile (both android & iOS) and I want to implement a local multiplayer (on same wifi network/bluetooth) functionality in the game. What could be the best option to do this ??
it would be great if it is cross platform (android <-> iOS)
if i use peer-to-peer and Adobe Cirrus service (RTMFP) for local multiplayer, can I get into any problems, since the project is in beta ??
I already know about this post : http://forum.starling-framework.org/topic/google-play-game-services-ane-1#post-74449
I have also gone through this post : http://www.as3gamegears.com/category/multiplayer/ But some of the options that I like uses RTMFP which I am doubtful about !! So please suggest me if its ok to use ??
can I use Datagram Sockets class provided by the AIR sdk..?? Although I am not sure but is there any connection between RTMFP and TCP/Datagram sockets ??
If I any more details are required I can specify !!!
Thanks
I use Adobe Cirrus and it's work well. I used available docs and it takes me about 30 min to start communication between two devices. In my opinion it is best choice.
You can use RTMFP without Cirrus using the LAN NetGroup method.
This method is described in the documentation for NetConnection/connect():
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/net/NetConnection.html#connect()
A good example of this can be found here:
http://tomkrcha.com/?p=1803
private var connection:NetConnection;
private var group:NetGroup;
private function connect():void {
connection = new NetConnection();
connection.connect("rtmfp:");
connection.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
}
private function netStatus(event:NetStatusEvent):void {
switch(event.info.code){
case "NetConnection.Connect.Success":
joinGroup();
break;
case "NetGroup.Posting.Notify":
receive(event.info.message);
break;
}
}
private function joinGroup():void{
var groupspec:GroupSpecifier = new GroupSpecifier("myGroup/groupOne");
groupspec.postingEnabled = true;
groupspec.ipMulticastMemberUpdatesEnabled = true;
groupspec.addIPMulticastAddress("225.225.0.1:30303");
group = new NetGroup(connection, groupspec.groupspecWithAuthorizations());
group.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
}
public function send(text:String):void {
var message:Object = {
sender: connection.nearId,
text: text
}
group.post(message);
}
public function receive(message:Object):void {
trace("Received message from " + message.sender + ": " + message.text);
}
This is in my experienced the easiest way to do multi-user apps on a local network, because it requires no server (even to discover neighbors) and just the Flash Player.
You can try to use Bluetooth Low Energy in AIR for iOS(and OSX).
Demonstration here: http://www.youtube.com/watch?v=tiRfYjq4wh0&index=1&list=PLw76-mHQ5mhdmHPJy05n424-DKde1XM8G . ANE library here: http://flashpress.ru/blog/ane/bluetooth/?lang=en
CentralManager:
package
{
import flash.display.Sprite;
import ru.flashpress.ane.queue.FPQueueData;
import ru.flashpress.ane.queue.FPQueueTypes;
import ru.flashpress.bluetooth.FPBluetooth;
import ru.flashpress.bluetooth.constants.FPbtState;
import ru.flashpress.bluetooth.data.FPBluetoothOptions;
import ru.flashpress.bluetooth.events.FPBluetoothEvent;
import ru.flashpress.bluetooth.events.FPCentralManagerEvent;
import ru.flashpress.bluetooth.events.FPCharacteristicEvent;
import ru.flashpress.bluetooth.events.FPPeripheralEvent;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristic;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicValueFormat;
import ru.flashpress.bluetooth.helpers.characteristic.stream.FPStreamIn;
import ru.flashpress.bluetooth.helpers.peripheral.FPPeripheral;
import ru.flashpress.bluetooth.helpers.service.FPService;
import ru.flashpress.bluetooth.helpers.service.FPServiceEvent;
import ru.flashpress.bluetooth.managers.central.FPCentralManager;
import ru.flashpress.bluetooth.managers.central.FPcmScanOptions;
public class CentralView extends Sprite
{
public static const SERVICE_UUID:String = 'E20A39F4-73F5-4BC4-A12F-17D1AD07A961';
public static const CHARACTERISTIC_UUID:String = '08590F7E-DB05-467E-8757-72F6FAEB13D4';
//
public function CentralView()
{
var options:FPBluetoothOptions = new FPBluetoothOptions();
options.nativeLogEnabled = true;
FPBluetooth.init(options);
//
startBluetooth();
}
// Bluetooth Methods ****************
private var cm:FPCentralManager;
private function startBluetooth():void
{
trace('startBluetooth');
var queue:FPQueueData = new FPQueueData('ru.flashpress.chat.central', FPQueueTypes.SERIAL);
cm = new FPCentralManager(null, queue);
cm.addEventListener(FPBluetoothEvent.UPDATE_STATE, updateStateHandler);
cm.addEventListener(FPCentralManagerEvent.PERIPHERAL_DISCOVER, discoverPeripheralHandler);
}
private function updateStateHandler(event:FPBluetoothEvent):void
{
trace('updateStateHandler', event.state);
if (event.state != FPbtState.POWERED_ON) {
return;
}
var options:FPcmScanOptions = new FPcmScanOptions(true, null);
cm.startScan(options, SERVICE_UUID);
}
private var peripheral:FPPeripheral;
private function discoverPeripheralHandler(event:FPCentralManagerEvent):void
{
trace('discoverPeripheralHandler', event.peripheral);
if (peripheral) return;
peripheral = event.peripheral;
trace(' name:', peripheral.advertisementInited ? peripheral.advertisementInited.localName : null);
//
peripheral.addEventListener(FPPeripheralEvent.CONNECTED, peripheralConnectedHandler);
peripheral.addEventListener(FPPeripheralEvent.DISCONNECT, peripheralDisconnectedHandler);
peripheral.connect();
}
private function peripheralConnectedHandler(event:FPPeripheralEvent):void
{
trace('peripheralConnectedHandler');
peripheral.discoverServiceUUIDs(SERVICE_UUID);
peripheral.addEventListener(FPPeripheralEvent.DISCOVER_SERVICES, discoverServicesHandler);
}
private function peripheralDisconnectedHandler(event:FPPeripheralEvent):void
{
trace('peripheralDisconnectedHandler');
peripheral.removeEventListener(FPPeripheralEvent.CONNECTED, peripheralConnectedHandler);
peripheral.removeEventListener(FPPeripheralEvent.DISCONNECT, peripheralDisconnectedHandler);
peripheral = null;
}
private var service:FPService;
private function discoverServicesHandler(event:FPPeripheralEvent):void
{
trace('discoverServicesHandler');
if (event.error) {
trace('discoverServicesHandler, error:', event.error);
return;
}
//
service = peripheral.services.list[0];
trace(' service:', service);
//
service.discoverCharacteristicUUIDs(CHARACTERISTIC_UUID);
service.addEventListener(FPServiceEvent.DISCOVER_CHARACTERISTICS, discoverCharacteristicsHandler);
}
public var characteristic:FPCharacteristic;
private var streamIn:FPStreamIn;
private function discoverCharacteristicsHandler(event:FPServiceEvent):void
{
trace('discoverCharacteristicsHandler');
if (event.error) {
trace('discoverCharacteristicsHandler, error:', event.error);
return;
}
characteristic = service.characteristics.list[0];
trace(' characteristic:', characteristic);
characteristic.initValueFormat(FPCharacteristicValueFormat.MESSAGES);
streamIn = characteristic.streamIn;
characteristic.setNotify(true);
characteristic.addEventListener(FPCharacteristicEvent.UPDATE_NOTIFICATION, updateNotificationHandler);
//
characteristic.addEventListener(FPCharacteristicEvent.UPDATE_MESSAGES, updateMessageHandler);
}
private function updateNotificationHandler(event:FPCharacteristicEvent):void
{
trace('updateNotificationHandler:', event.isNotifying);
}
private function updateMessageHandler(event:FPCharacteristicEvent):void
{
trace('updateMessageHandler');
trace(' error:', event.error);
trace(' messages:', event.messages);
}
}
}
Peripheral Manager:
package
{
import flash.display.Sprite;
import ru.flashpress.bluetooth.FPBluetooth;
import ru.flashpress.bluetooth.constants.FPbtState;
import ru.flashpress.bluetooth.data.FPAdvertisementData;
import ru.flashpress.bluetooth.data.FPBluetoothOptions;
import ru.flashpress.bluetooth.events.FPBluetoothEvent;
import ru.flashpress.bluetooth.events.FPCharacteristicEvent;
import ru.flashpress.bluetooth.events.FPPeripheralManagerEvent;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristic;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicPermissions;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicProperties;
import ru.flashpress.bluetooth.helpers.characteristic.FPCharacteristicValueFormat;
import ru.flashpress.bluetooth.helpers.service.FPService;
import ru.flashpress.bluetooth.managers.peripheral.FPPeripheralManager;
public class PeripheralView extends Sprite
{
public static const SERVICE_UUID:String = 'E20A39F4-73F5-4BC4-A12F-17D1AD07A961';
public static const CHARACTERISTIC_UUID:String = '08590F7E-DB05-467E-8757-72F6FAEB13D4';
//
public function PeripheralView()
{
var options:FPBluetoothOptions = new FPBluetoothOptions();
options.nativeLogEnabled = true;
FPBluetooth.init(options);
//
startBluetooth();
}
// Bluetooth Methods ****************
private var pm:FPPeripheralManager;
private function startBluetooth():void
{
trace('startBluetooth');
pm = new FPPeripheralManager();
pm.addEventListener(FPBluetoothEvent.UPDATE_STATE, updateStateHandler);
pm.addEventListener(FPPeripheralManagerEvent.ADD_SERVICE, addServiceHandler);
}
private var characteristic:FPCharacteristic;
private var service:FPService;
private function updateStateHandler(event:FPBluetoothEvent):void
{
trace('updateStateHandler:', event.state);
if (event.state != FPbtState.POWERED_ON) {
return;
}
//
var properties:uint = FPCharacteristicProperties.NOTIFY;
var permissions:uint = FPCharacteristicPermissions.WRITEABLE;
var valueFormat:uint = FPCharacteristicValueFormat.MESSAGES;
characteristic = new FPCharacteristic(CHARACTERISTIC_UUID, properties, permissions, valueFormat);
characteristic.addEventListener(FPCharacteristicEvent.SUBSCRIBED_TO_CENTRAL, subscribedToCentralHandler);
characteristic.addEventListener(FPCharacteristicEvent.UNSUBSCRIBED_FROM_CENTRAL, unsubscribedFromCentralHandler);
characteristic.notifyMTU = 50;
//
service = new FPService(SERVICE_UUID, true);
service.addCharacteristic(characteristic);
//
pm.addService(service);
}
private function addServiceHandler(event:FPPeripheralManagerEvent):void
{
trace('addServiceHandler');
if (event.error) {
trace(' error:', event.error);
return;
}
if (!pm.isAdvertising) {
var uuids:Vector. = new [SERVICE_UUID];
var advertisementData:FPAdvertisementData = new FPAdvertisementData('My Local name', uuids);
pm.startAdvertising(advertisementData);
}
}
private function unsubscribedFromCentralHandler(event:FPCharacteristicEvent):void
{
trace('unsubscribedFromCentralHandlers', event.central);
}
private function subscribedToCentralHandler(event:FPCharacteristicEvent):void
{
trace('subscribedToCentralHandler', event.central);
//
characteristic.sendMessage('send my message');
}
}
}

AS3 URLLoader POST aborted in browser

I've re-built an SWF audio uploader, and it was working fine for a few days. However, I just did a run-through of all the things I've built onto this project, and I notice that the POST request to the server to save the audio file is being Aborted about 10 seconds into the request. At 20 seconds, everything stops because of a timeout limitation that is implemented. I don't know much about AS3 or how it makes requests, but I do know that the PHP handler file is solid because no changes were made to it from the point which it worked last. The permissions are 755 and ownerships are correct on both the SWF and the handler file. I can also re-submit the request via Firebug, and it works with no issue whatsoever.
I'm not sure where the problem is stemming from exactly; whether it be browser, server or code issue. I was reading about Aborted requests and I've ensured that there are no other active requests before trying to upload. I should also add that other POST/GET requests have no issues, it's just this one request from the SWF.
Again, Flash/ActionScript is not a strength of mine, so if there are ways to improve what I'm doing, or if anyone can tell me what I'm doing wrong, please tell me.
package{
import flash.display.Sprite;
import flash.media.Microphone;
import flash.system.Security;
import org.bytearray.micrecorder.*;
import org.bytearray.micrecorder.events.RecordingEvent;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.ActivityEvent;
import fl.transitions.Tween;
import fl.transitions.easing.Strong;
import flash.net.FileReference;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.display.LoaderInfo;
import flash.external.ExternalInterface;
import flash.media.Sound;
import org.as3wavsound.WavSound;
import org.as3wavsound.WavSoundChannel;
import com.adobe.serialization.json.JSON;
import com.adobe.serialization.json.JSONDecoder;
public class Main extends Sprite{
private var mic:Microphone;
private var requestor:URLLoader;
private var waveEncoder:WaveEncoder = new WaveEncoder();
private var recorder:MicRecorder = new MicRecorder(waveEncoder);
private var recBar:RecBar = new RecBar();
private var maxTime:Number = 30;
private var tween:Tween;
private var fileReference:FileReference = new FileReference();
private var tts:WavSound;
public function Main():void{
trace('recoding');
recButton.visible = false;
activity.visible = false ;
godText.visible = false;
recBar.visible = false;
mic = Microphone.getMicrophone();
mic.setSilenceLevel(5);
mic.gain = 50;
mic.setLoopBack(false);
mic.setUseEchoSuppression(true);
Security.showSettings("2");
requestor = new URLLoader();
addListeners();
}
private function addListeners():void{
recorder.addEventListener(RecordingEvent.RECORDING, recording);
recorder.addEventListener(Event.COMPLETE, recordComplete);
activity.addEventListener(Event.ENTER_FRAME, updateMeter);
//accept call from javascript to start recording
ExternalInterface.addCallback("startRecording", startRecording);
ExternalInterface.addCallback("stopRecording", stopRecording);
ExternalInterface.addCallback("sendFileToServer", sendFileToServer);
}
//external java script function call to start record
public function startRecording(max_time):void{
maxTime = max_time;
if(mic != null){
recorder.record();
ExternalInterface.call("$.audioRec.callback_started_recording");
}else{
ExternalInterface.call("$.audioRec.callback_error_recording", 0);
}
}
//external javascript function to trigger stop recording
public function stopRecording():void{
recorder.stop();
mic.setLoopBack(false);
ExternalInterface.call("$.audioRec.callback_stopped_recording");
}
public function sendFileToServer():void{
finalize_recording();
}
public function stopPreview():void{
//no function is currently available;
}
private function updateMeter(e:Event):void{
ExternalInterface.call("$.audioRec.callback_activityLevel", mic.activityLevel);
}
private function recording(e:RecordingEvent):void{
var currentTime:int = Math.floor(e.time / 1000);
ExternalInterface.call("$.audioRec.callback_activityTime", String(currentTime));
if(currentTime == maxTime ){
stopRecording();
}
}
private function recordComplete(e:Event):void{
preview_recording();
}
private function preview_recording():void{
tts = new WavSound(recorder.output);
tts.play();
ExternalInterface.call("$.audioRec.callback_started_preview");
}
//function send data to server
private function finalize_recording():void{
var _var1:String= '';
var globalParam = LoaderInfo(this.root.loaderInfo).parameters;
for(var element:String in globalParam){
if(element == 'host'){
_var1 = globalParam[element];
}
}
ExternalInterface.call("$.audioRec.callback_finished_recording");
if(_var1 != ''){
ExternalInterface.call("$.audioRec.callback_started_sending");
var req:URLRequest = new URLRequest(_var1);
req.contentType = 'application/octet-stream';
req.method = URLRequestMethod.POST;
req.data = recorder.output;
requestor.addEventListener(Event.COMPLETE, requestCompleteHandler);
requestor.load(req);
}
}
private function requestCompleteHandler(event:Event){
ExternalInterface.call("$.audioRec.callback_finished_sending", requestor.data);
}
private function getFlashVars():Object{
return Object(LoaderInfo(this.loaderInfo).parameters);
}
}
}

Record Sound Using AS3 Worker

Hello I am trying to record the user sound using AS3 Worker everything works well when it comes to communication between the worker and the main scene but I think the record functionnality have and issue here I am using the Record Clash from bytearray.org (http://www.bytearray.org/?p=1858)
and here's is my code am I missing something :
package objects
{
import flash.events.Event;
import flash.system.MessageChannel;
import flash.system.Worker;
import flash.system.WorkerDomain;
import flash.utils.ByteArray;
import starling.display.Button;
import starling.display.Image;
import starling.display.Sprite;
import starling.events.Event;
public class RecordComponent extends Sprite
{
private var audioContainer:Image;
private var recButton:Button;
private var playButton:Button;
private var stopButton:Button;
//background thread for recording
private var worker:Worker;
private var wtm:MessageChannel;
private var mtw:MessageChannel;
private var output:ByteArray;
public function RecordComponent()
{
super();
worker = WorkerDomain.current.createWorker(Workers.RecordWorker);
wtm = worker.createMessageChannel(Worker.current);
mtw = Worker.current.createMessageChannel(worker);
worker.setSharedProperty("wtm",wtm);
worker.setSharedProperty("mtw",mtw);
worker.start();
wtm.addEventListener(flash.events.Event.CHANNEL_MESSAGE,onChannelMessage);
this.addEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
}
protected function onChannelMessage(event:flash.events.Event):void
{
output = wtm.receive();
}
protected function onAddedToStage(event:starling.events.Event):void
{
this.removeEventListener(starling.events.Event.ADDED_TO_STAGE, onAddedToStage);
drawScreen();
}
private function drawScreen():void
{
audioContainer = new Image( Assets.getAtlas().getTexture("audioContainer") );
addChild(audioContainer);
//record button
recButton = new Button( Assets.getAtlas().getTexture("recordButton") );
recButton.x=Math.ceil(194/2 - recButton.width/2);
recButton.y=5;
addChild(recButton);
//stop button
stopButton = new Button( Assets.getAtlas().getTexture("stopButton") );
stopButton.x=recButton.x+10;
stopButton.y=10;
stopButton.visible = false;
addChild(stopButton);
//play button
playButton = new Button( Assets.getAtlas().getTexture("playButton") );
playButton.x=Math.ceil(194 - playButton.width)-25;
playButton.y=10;
playButton.visible = false;
addChild(playButton);
this.addEventListener(starling.events.Event.TRIGGERED, buttons_triggeredHandler);
}
private function buttons_triggeredHandler(event:starling.events.Event):void
{
var currentButton:Button = event.target as Button;
switch(currentButton)
{
case recButton:
startRecording();
break;
case stopButton:
stopRecording();
break;
case playButton:
playRecording();
break;
}
}
private function playRecording():void
{
mtw.send("RECORD_PLAY");
}
private function stopRecording():void
{
stopButton.visible = false;
recButton.x = 25;
playButton.visible = true;
recButton.visible = true;
mtw.send("RECORD_STOP");
//
}
private function startRecording():void
{
recButton.visible = false;
stopButton.visible = true;
playButton.visible = false;
mtw.send("RECORD_START");
}
}
}
RecordWorker
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.media.Microphone;
import flash.system.MessageChannel;
import flash.system.Worker;
import org.as3wavsound.WavSound;
import org.bytearray.micrecorder.MicRecorder;
import org.bytearray.micrecorder.encoder.WaveEncoder;
import org.bytearray.micrecorder.events.RecordingEvent;
public class RecordWorker extends Sprite
{
private var wtm:MessageChannel;
private var mtw:MessageChannel;
// volume in the final WAV file will be downsampled to 50%
private var volume:Number = .75;
// we create the WAV encoder to be used by MicRecorder
private var wavEncoder:WaveEncoder = new WaveEncoder( volume );
// we create the MicRecorder object which does the job
private var recorder:MicRecorder = new MicRecorder( wavEncoder,Microphone.getEnhancedMicrophone() );
public function RecordWorker()
{
wtm = Worker.current.getSharedProperty("wtm");
mtw = Worker.current.getSharedProperty("mtw");
mtw.addEventListener(Event.CHANNEL_MESSAGE,command_Handler);
}
//message received from the main component
protected function command_Handler(event:Event):void
{
switch(mtw.receive())
{
case "RECORD_START":
trace("recording.....");
recorder.record();
recorder.addEventListener(RecordingEvent.RECORDING, onRecording);
recorder.addEventListener(flash.events.Event.COMPLETE, onRecordComplete);
break;
case "RECORD_STOP":
trace("record stopped....");
recorder.stop();
break;
case "RECORD_PLAY":
if(recorder.output.length>0)
{
var player:WavSound = new WavSound(recorder.output);
player.play();
}
break;
}
}
private function onRecording(event:RecordingEvent):void
{
trace ( event.time );
}
private function onRecordComplete(event:flash.events.Event):void
{
}
}
}
anny help will be appriciated
Thanks,
Khaled
Looking at this write-up on Adobe's AS3 reference, it seems that because each created worker is "a virtual instance of the Flash runtime", it has no direct connection to any of the core runtime's input or output channels. The Microphone class is one such cut-off interface, which is why it can't reach the system mic inside a worker.

Better way to send voice over a socket in AS3

I made an AIR application that sends voice between two computers, this is the code:
package
{
import fl.controls.List;
import flash.events.ProgressEvent;
import flash.events.SampleDataEvent;
import flash.events.ServerSocketConnectEvent;
import flash.media.Microphone;
import flash.media.Sound;
import flash.net.ServerSocket;
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.system.System;
public class VoiceCommunication
{
private var soundBytes:ByteArray;
private var mic:Microphone;
private var voiceReceiver:ServerSocket;
private var voiceSender:Socket;
private var mLocalIP:String;
private var mRemoteIP:String;
private var mPort:uint;
private var sound:Sound;
private var sample:Number;
public function VoiceCommunication(localIP:String, port:uint)
{
mLocalIP = localIP;
mPort = port;
}
public function startSendingVoice(remoteIP:String = null):void
{
mic = Microphone.getMicrophone();//2-null
mic.gain = 100;
mic.rate = 44;
voiceSender = new Socket();//3-null
mRemoteIP = remoteIP;//5-null
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);//1-remove eventlistener
}
protected function micSampleDataHandler(event:SampleDataEvent):void
{
if(mRemoteIP != null)
{
voiceSender.connect(mRemoteIP, mPort);
while(event.data.bytesAvailable)
{
sample = event.data.readFloat();
voiceSender.writeFloat(sample);
}
voiceSender.flush();
}
}
public function startReceivingVoice():void
{
voiceReceiver = new ServerSocket;//2
voiceReceiver.bind(mPort, mLocalIP);
voiceReceiver.addEventListener(ServerSocketConnectEvent.CONNECT, handleConnection);//1
voiceReceiver.listen();
}
protected function handleConnection(event:ServerSocketConnectEvent):void
{
var s:Socket = event.socket as Socket;
s.addEventListener(ProgressEvent.SOCKET_DATA, handleData);
}
protected function handleData(event:ProgressEvent):void
{
event.target.removeEventListener(ProgressEvent.SOCKET_DATA, handleData);
var s:Socket = event.target as Socket;
soundBytes = null;
soundBytes = new ByteArray();//3
s.readBytes(soundBytes);
playSound();
s = null;
}
private function playSound():void
{
soundBytes.position = 0;
sound = null;
sound = new Sound();//5
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);//4
sound.play();
}
protected function playbackSampleHandler(event:SampleDataEvent):void
{
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++)
{
sample = soundBytes.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
System.gc();
}
public function destroySender():void
{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
mic = null;
voiceSender = null;
mRemoteIP = null;
System.gc();
}
public function destroyReceiver():void
{
voiceReceiver.removeEventListener(ServerSocketConnectEvent.CONNECT, handleConnection);//1
voiceReceiver = null;
soundBytes = null;
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
sound = null;
System.gc();
}
}
}
This works fine and when I tried it, it did send the voice, but the problem is that sending the voice is too slow and gets split. So is there a better way to do it?
I rewrote it using datagram socket but that didn't work at all, the code:
package
{
import fl.controls.List;
import flash.events.DatagramSocketDataEvent;
import flash.events.ProgressEvent;
import flash.events.SampleDataEvent;
import flash.events.ServerSocketConnectEvent;
import flash.media.Microphone;
import flash.media.Sound;
import flash.net.DatagramSocket;
import flash.net.ServerSocket;
import flash.net.Socket;
import flash.system.System;
import flash.utils.ByteArray;
public class VoiceComm
{
private var soundBytes:ByteArray;
private var mic:Microphone;
private var socket:DatagramSocket
private var mList:List;
private var mLocalIP:String;
private var mRemoteIP:String;
private var mPort:uint;
private var sound:Sound;
private var sample:Number;
private var bytesToBeSent:ByteArray;
public function VoiceComm(localIP:String, port:uint)
{
socket = new DatagramSocket();
mLocalIP = localIP;
mPort = port;
}
public function startSendingVoice(remoteIP:String = null):void
{
mic = Microphone.getMicrophone();
mic.gain = 100;
mic.rate = 44;
mRemoteIP = remoteIP;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
}
protected function micSampleDataHandler(event:SampleDataEvent):void
{
var sample:Number;
if(mRemoteIP != null)
{
while(event.data.bytesAvailable)
{
sample = event.data.readFloat();
bytesToBeSent = null;
bytesToBeSent = new ByteArray();
bytesToBeSent.writeFloat(sample);
socket.send(bytesToBeSent, 0, 0, mRemoteIP, mPort);
}
}
}
public function startReceivingVoice():void
{
socket.bind(mPort, mLocalIP);
socket.addEventListener(DatagramSocketDataEvent.DATA, handleData);
socket.receive();
}
protected function handleData(event:DatagramSocketDataEvent):void
{
trace("Data inthere!");
soundBytes = null;
soundBytes = new ByteArray();//3
event.data.readBytes(soundBytes);
playSound();
}
private function playSound():void
{
soundBytes.position = 0;
sound = null;
sound = new Sound();//5
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);//4
sound.play();
}
protected function playbackSampleHandler(event:SampleDataEvent):void
{
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
for (var i:int = 0; i < 8192 && soundBytes.bytesAvailable > 0; i++)
{
sample = soundBytes.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
}
System.gc();
}
public function destroySender():void
{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, micSampleDataHandler);
mic = null;
mList = null;
mRemoteIP = null;
System.gc();
}
public function destroyReceiver():void
{
soundBytes = null;
sound.removeEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler);
sound = null;
System.gc();
}
}
}
**Update:
The code after modification:
package
{
import fl.controls.List;
import flash.events.DatagramSocketDataEvent;
import flash.events.SampleDataEvent;
import flash.media.Microphone;
import flash.media.Sound;
import flash.net.DatagramSocket;
import flash.net.Socket;
import flash.system.System;
import flash.utils.ByteArray;
public class VoiceComm
{
private var mic:Microphone;
private var soundBytes:ByteArray;
private var sample:Number;
private var sound:Sound;
private var socket:DatagramSocket;
private var mLocalIP:String;
private var mPort:uint;
private var mRemoteIP:String;
private var receivedBytes:ByteArray;
public function VoiceComm(localIP:String, port:uint)
{
socket = new DatagramSocket();
mLocalIP = localIP;
mPort = port;
}
//destroyers:
public function destroySender():void
{
mic.removeEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);
mic = null;
soundBytes = null;
System.gc();
}
public function destroyReceiver():void
{
socket.removeEventListener(DatagramSocketDataEvent.DATA, playSound);
receivedBytes = null;
System.gc();
}
//sending part
public function startSendingVoice(ip:String = null):void
{
mRemoteIP = ip;
mic = Microphone.getMicrophone();
mic.rate = 44;
mic.gain = 100;
mic.addEventListener(SampleDataEvent.SAMPLE_DATA, sampleData);
}
protected function sampleData(event:SampleDataEvent):void
{
soundBytes = new ByteArray();
while(event.data.bytesAvailable)
{
var sample:Number = event.data.readFloat();
soundBytes.writeFloat(sample);
}
if(mRemoteIP != null)
{
event.data.position = 0;
socket.send(soundBytes, 0, event.data.length, mRemoteIP, mPort);
}
}
//receiving part
public function startReceivingVoice():void
{
socket.bind(mPort, mLocalIP);
socket.addEventListener(DatagramSocketDataEvent.DATA, playSound);
socket.receive();
}
protected function playSound(event:DatagramSocketDataEvent):void
{
trace("got data!");
receivedBytes = new ByteArray();
event.data.readBytes(receivedBytes);
receivedBytes.position = 0;
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, playbackSampleHandler, false, 0, true);
sound.play();
}
protected function playbackSampleHandler(event:SampleDataEvent):void
{
trace("Playing Sound...");
for (var i:int = 0; i < 8192 && receivedBytes.bytesAvailable > 0; i++)
{
var sample:Number = receivedBytes.readFloat();
event.data.writeFloat(sample);
event.data.writeFloat(sample);
System.gc();
}
}
}
}
This is most likely the source of the issue: http://forums.adobe.com/message/3111816. The TCP Nagle Algorithm. What this basically does is, when you're writing a bunch of small chunks of data to the socket, instead of sending them all out individually it will hold them back and pool them together in order to send a single "full" packet rather than tons of small ones (which leads to a greater, constant load on the network).
If possible, re-write using Datagram sockets instead. To my knowledge there is currently no way to disable the Nagle algorithm in Flash.
Update
A couple things after looking at your code in depth: The first is that you're writing each byte one at a time to the TCP socket. Don't do that, write the entire bytearray and flush it.
if(mRemoteIP != null)
{
voiceSender.connect(mRemoteIP, mPort);
voiceSender.writeBytes(event.data, 0, event.data.length);
voiceSender.flush();
}
That may solve the issues you're having. If not, the reason why your UDP version is for two reasons. The first is that again, you're writing one byte at a time and sending but more important, you're telling it not to write the data to the socket at all. This line is the culprit:
socket.send(bytesToBeSent, 0, 0, mRemoteIP, mPort);
Note the third paramter, "0". That parameter is the amount of data from the supplied bytearray that should be written to the socket. So you're essentially saying, don't send anything. Change the code like so:
if(isConnected == true)
{
event.data.position = 0;
localSendingSocket.send(event.data, 0, event.data.length, remoteIP, remotePort);
}
Let me know if this works out for you. In the meantime I'm re-writing your code based on these suspicions so if I manage to get a project compiled and working before you, I'll post the project files here.
Where not use Adobe Cirrus (formerly Stratus to create a peer2peer application instead of the socket?
use the (OS) Red5 server.
http://www.red5.org/
the blurb:
"Red5 Media Server 1.0 delivers a powerful video streaming and multi-user solution to the ©Adobe ©Flash Player and other exciting client technologies. Based on Java and some of the most powerful open source frameworks, Red5 stands as a solid solution for business of all sizes including the enterprise.
Red5 includes support for the latest multi-user API’s including NetConnection, NetStream and SharedObject’s while providing a powerful RTMP / Servlet implementation. In addition to support for the RTMP protocol, the application server has an embedded Tomcat Servlet container for Java EE Web Applications. Application development draws additional benefits from the Spring Framework and Scope based event driven services.
By using the Open Source Red5 Media Server, you are developing with a truly open and extensible platform that can be used in Video Conferences, Multi-User Gaming and Enterprise Application Software.
Happy Coding and enjoy our powerful free community server"

sound stream stops loading

I have a little sound stream script here, but sometimes if you press play to the next track before the current has done loading the next track doesn't comeplete loading
package player {
import flash.events.Event;
import flash.display.Sprite;
import flash.external.ExternalInterface;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
import player.Loader_bar;
public class Stream extends Sprite {
private var _Sound = null;
private var _Channel = null;
private var isLoading = false;
private var _Loader_bar = null;
public var loader_color = null;
public var loader_width = 0;
public var loader_height = 0;
private var i = 0;
public function Stream(){
this._Loader_bar = new Loader_bar();
addChild(this._Loader_bar);
}
public function cnstr(){
this._Loader_bar.color = this.loader_color;
this._Loader_bar.w = this.loader_width;
this._Loader_bar.h = this.loader_height;
this._Loader_bar.cnstr();
}
public function play(url){
this.stop();
this.close();
this._Sound = new Sound();
this.isLoading = true;
this.addEventListener(Event.ENTER_FRAME, listener_bytesLoaded);
this._Sound.addEventListener(Event.COMPLETE, listener_loadedComplete);
this._Sound.load(new URLRequest(url));
this._Channel = this._Sound.play();
}
public function stop(){
if(this._Channel){
this._Channel.stop();
}
}
private function close(){
if(this.isLoading){
this._Sound.close();
}
}
private function listener_loadedComplete(event){
this.close();
this.isLoading = false;
this.removeEventListener(Event.ENTER_FRAME, listener_bytesLoaded);
}
private function listener_bytesLoaded(event){
var float = this._Sound.bytesLoaded / this._Sound.bytesTotal;
this._Loader_bar.progress(float);
var data = {
i : this.i,
float : float,
loaded : this._Sound.bytesLoaded,
total : this._Sound.bytesTotal
};
ExternalInterface.call('swf2js', 'tst_progress', data);
this.i++;
}
}
}
close():void
Closes the stream, causing any download of data to cease.
try this:
create a boolean like hasLoaded, set it to false. When the sound successfully loads set it to true.
Then when you play a sound you can test for hasLoaded in your play() function. If you have called play() before your previous sound has loaded, hasLoaded will be false, in which case you call this._Sound.close() before creating and loading the new sound. The reason for testing instead of just calling close() is so if you have paused the stream you don't have to reload it to play it again.
ADDITION:
Concerning the load not reporting properly, you have your progress logic set up incorrectly. Try this:
1) import flash.events.ProgressEvent
2) For the listener, replace this.addEventListener(Event.ENTER_FRAME, listener_bytesLoaded); in your play() method with this._Sound.addEventListener(ProgressEvent.PROGRESS, listener_bytesLoaded);
3) Change your listener_bytesLoaded() method to the following:
private function listener_bytesLoaded(event:ProgressEvent)
{
var percent = event.bytesLoaded / event.bytesTotal;
this._Loader_bar.progress(percent);
var data = {
i : this.i,
float : percent,
loaded : event.bytesLoaded,
total : event.bytesTotal
};
ExternalInterface.call('swf2js', 'tst_progress', data);
this.i++;
}
4) Change this.removeEventListener(Event.ENTER_FRAME, listener_bytesLoaded);
in your listener_loadedComplete() method to this._Sound.removeEventListener(ProgressEvent.PROGRESS, listener_bytesLoaded); and then move it out of that method and place it inside the conditional in the close() method.
NOTE - I didn't actually compile this but I think its good to go. Hope that helps. :)