ActionScript 3 onMetaData video duration - can't store value - actionscript-3

I have standard NetStream for video connection in AS3:
The Code:
public class VideoInit extends MovieClip
{
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
public var video:Video;
public var nc:NetConnection;
public var ns:NetStream;
public var meta:Object;
public var _duration; // <----- the variable
public function VideoInit()
{
video = new Video(480,270);
addChild(video);
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
meta = new Object();
ns.client = meta;
video.attachNetStream(ns);
ns.play("video.f4v");
meta = new Object();
meta.onMetaData = function(meta:Object) // <---- the method
{
_duration = meta.duration
}
ns.client = meta;
}
Now, everyime that the onMetaData method executes, the variable _duration stores the value, but right after the debugger step leaves the method, _duration value is set back to unindentified.
I've tried to do a workaround with Array, by pushing the value, but the same thing happens, the Array resets. What could it be wrong?
Edit:
Any object that stores the duration value self destructs as soon as onMetaData is complete. Doesn't really matter how I Implement it.

The code you've posted would not compile and, even if it did, it could cause other problems.
Suggestion: ditch the meta Object and instead set ns.client = this;
This works:
package
{
import flash.events.Event;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.events.NetStatusEvent;
public class VideoInit extends Sprite
{
private var video:Video;
private var nc:NetConnection;
private var ns:NetStream;
private var _duration:Number; // <----- the variable
public function VideoInit()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
video = new Video(480,270);
addChild(video);
nc = new NetConnection();
nc.connect(null);
ns = new NetStream(nc);
ns.client = this;// meta;
video.attachNetStream(ns);
ns.play("video.f4v");
stage.addEventListener(MouseEvent.MOUSE_DOWN, testTheValueOfDuration);
}
public function onMetaData(e:Object):void
{
_duration = e.duration
trace('_duration:', _duration);
testTheValueOfDuration();
}
private function testTheValueOfDuration(e:MouseEvent = null):void
{
trace('Seriously, what is the value of _duration?', _duration);
}
}
}

Related

StageVideo problems

i'm trying some examples founded on the web but don't works...
the code :
package{
import flash.display.Sprite;
import flash.events.StageVideoAvailabilityEvent;
import flash.media.StageVideo;
import flash.events.StageVideoEvent;
import flash.geom.Rectangle;
import flash.media.StageVideoAvailability;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.display.DisplayObjectContainer;
public class myStageVideo extends Sprite{
private var stageVideoAvail:Boolean;
private var sv:StageVideo;
public function myStageVideo(container:DisplayObjectContainer){
container.addChild(this);
container.addEventListener(StageVideoAvailabilityEvent.STAGE_VIDEO_AVAILABILITY, onAvail);
}
private function onAvail(e:StageVideoAvailabilityEvent):void{
trace("arrivato a onAvail");
stageVideoAvail = (e.availability == StageVideoAvailability.AVAILABLE);
initVideo();
}
private function initVideo():void{
var nc:NetConnection = new NetConnection();
nc.connect(null);
var ns:NetStream = new NetStream(nc);
ns.client = this;
stageVideoAvail = true;
if(stageVideoAvail){
sv = stage.stageVideos[0];
sv.addEventListener(StageVideoEvent.RENDER_STATE, onRender);
sv.attachNetStream(ns);
trace('available');
}
else{
var vid:Video = new Video(1024, 768);
addChild(vid);
vid.attachNetStream(ns);
trace('not');
}
ns.play('video.mp4');
}
private function onRender(e:StageVideoEvent):void{
sv.viewPort = new Rectangle(0, 0, 1024, 768);
}
public function onMetaData(e:Object):void{
}
public function onXMPData(e:Object):void{
}
}
}
what am I doing wrong? I'm trying from a week, but nothing...
the video.mp4 is in the same folder.
i think 1 error
It is the way in which I add the child to the container

AS3 Error 1195:

I am getting the following errors:
C:\Users\Admin\Desktop\Final Project\Main.as, Line 80, Column 14 1195:
Attempted access of inaccessible method setTrackData through a
reference with static type LoadSND.
Relevant code
package {
import flash.display.MovieClip;
import flash.text.TextField;
import flash.display.SimpleButton;
import flash.utils.Dictionary;
import flash.text.TextFormat;
import flash.net.*;
import flash.events.*;
import fl.controls.*;
import flash.media.*;
import fl.events.ComponentEvent;
import fl.managers.StyleManager;
import fl.data.DataProvider;
import fl.data.SimpleCollectionItem;
import fl.managers.StyleManager;
import fl.events.ComponentEvent;
import flash.events.Event;
import flash.net.SharedObject;
import LoadSWF;
import GameButton;
import LoadSND;
public class Main extends MovieClip {
//Declare variables
private var componentFmt: TextFormat;
private var radioBtnFmt: TextFormat;
private var playerData: Object;
private var savedGameData: SharedObject;
// Pop-up Variables
private var popupFile: LoadSWF;
private var swfPath: String;
private var swfFile: LoadSWF;
//Sound Variables
private var MAX_TRAX: int = 7;
private var MAX_SFX: int = 9;
private var sndPath: String;
private var sndTrack: LoadSND;
private var isMuted: Boolean;
private var canRepeat: Boolean;
private var sndVolume: Number;
private var sndChannel: SoundChannel;
public function Main() {
// constructor code
this.savedGameData = SharedObject.getLocal("savedPlayerData");
this.setComponents();
this.setPlayerData();
swfPath = "";
sndPath = "musicSFX/Fury.mp3"; //default track
isMuted = false;
sndTrack = new LoadSND(sndPath, canRepeat);
}
/********************************************************
Load SND Functions***************************************
********************************************************/
private function setSound(evt: Event): void {
// Process COMBO BOX changes
if (musicCombo.selectedItem.data == "none") {
// no music is required so stop sound playing
SoundMixer.stopAll();
} else {
// otherwise load in the selected music
sndPath = "musicSFX/" + musicCombo.selectedItem.data;
sndTrack.setTrackData(sndPath, canRepeat);
}
}
private function setSlider(evt: Event): void {
// identify the button clicked
var mySlider: Object = (evt.target);
// adjusting to volume of the music channel to slider value
sndTrack.setVolumeLevel(mySlider.value);
}
private function setVolumeLevel(myVolume: Number): void {
// change the volume when slider changed
sndVolume = myVolume;
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
}
Also: the LoadSND Class
package {
import flash.events.*;
import flash.media.*;
import flash.net.URLRequest;
import flash.display.MovieClip;
public class LoadSND extends MovieClip {
//declare variables
private var sndTrack: Sound;
private var sndChannel: SoundChannel;
private var sndVolume: Number;
private var newTrack: String;
private var canRepeat: Boolean;
public function LoadSND(myTrack: String, myRepeat: Boolean = true) {
// constructor code
// set a default volume and track
sndVolume = 0.5;
setTrackData(myTrack, myRepeat);
}
private function loadSound(): void {
// first stop all old sounds playing
SoundMixer.stopAll();
// create a new sound for the track and a new sound channel
sndTrack = new Sound();
sndChannel = new SoundChannel();
// load the required sound
sndTrack.load(new URLRequest(newTrack));
// when loaded – play it;
sndTrack.addEventListener(Event.COMPLETE, soundLoaded);
}
private function soundLoaded(evt: Event): void {
// finished with this listener so remove it
//sndTrack.removeEventListener(Event.COMPLETE, soundLoaded);
// call the play sound function
playSound();
}
private function playSound(): void {
// assign music to the musicChannel and play it
sndChannel = sndTrack.play();
// setting the volume control property to the sound channel
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
// but add this one to make repeats
sndChannel.addEventListener(Event.SOUND_COMPLETE, playAgain);
}
private function playAgain(evt: Event): void {
// remove this listener and repeat playSound()
sndChannel.removeEventListener(Event.SOUND_COMPLETE, playAgain);
playSound();
}
private function setTrackData(myTrack: String, myRepeat: Boolean): void {
// update the new track information
newTrack = myTrack;
canRepeat = myRepeat;
// and load it
loadSound();
}
private function setVolumeLevel(myVolume: Number): void {
// change the volume when slider changed
sndVolume = myVolume;
sndChannel.soundTransform = new SoundTransform(sndVolume, 0);
}
} //end class
} //end package
Appreciate all the help :) thanks
Your setTrackData function in LoadSND class is private. you need to change type of the function to public so that you have access this function from the main class.
so change you function like this
public function setTrackData(myTrack: String, myRepeat: Boolean): void {
// update the new track information
newTrack = myTrack;
canRepeat = myRepeat;
// and load it
loadSound();
}

Using stage.addEventListener inside a class is returning a null object reference during runtime

I want to add an event listener to the stage from inside a class called "ChoiceBtn".
I get the error "1009: Cannot access a property or method of a null object reference". I understand that this is because the object is not yet instantiated.
Here is my code:
My main document code:
import ChoiceBtn;
var op1:ChoiceBtn = new ChoiceBtn("display meee", answer, 1, "a)", "4.jpg");
op1.x = 250;
op1.y = 60;
stage.addChild(op1);
My Class file:
package {
import AnswerEvent;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.SimpleButton;
import flash.events.*;
import flash.ui.Mouse;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.net.URLRequest;
import flash.display.Stage;
public class ChoiceBtn extends Sprite{
public var path:String;
public var choiceText:String;
public var choiceLabel:String;
private var answer:Answer;
private var choiceNum:uint;
private var textFormat:TextFormat = new TextFormat();
private var choiceLabelHwd:TextField = new TextField();
private var choiceTextHwd:TextField = new TextField();
private var boundingRect:Sprite = new Sprite;
private var hitAreaWidth = 255;
private var hitAreaHeight = 45;
private var pic:Loader = new Loader;
public function ChoiceBtn(choiceText:String, answer:Answer, choiceNum:uint, choiceLabel:String = "a)", picPath:String = null) {
//path - must be the path to a picture
//choiceText - the text to be displayed
//choiceLabel - the prefix selector such as answers '1' or 'a)' etc.
// constructor code
this.answer = answer;
this.choiceNum = choiceNum;
this.choiceLabel = choiceLabel;
this.choiceText = choiceText;
//add childs
addChild(this.choiceTextHwd);
addChild(this.choiceLabelHwd);
addChild(this.boundingRect); //must be added last so is on top of everything else
//add Listeners
//stage.addEventListener(AnswerEvent.EVENT_ANSWERED, update); //doesn't work
stage.addEventListener(AnswerEvent.EVENT_ANSWERED, this.update); //doesn't work either
}
public function update(e:Event):void {
trace("in choice fired");
}
}
}
I don't understand why it doesn't work even when I use this before the function. How can I create the eventlistener on the stage in this classes constructor code and reference a function inside this class.
Wait for the ADDED_TO_STAGE event to fire first:
public function ChoiceButton():void
{
// your code.. etc..
addEventListener(Event.ADDED_TO_STAGE,addListeners);
}
private function addListeners(event:Event):void
{
stage.addEventListener(AnswerEvent.EVENT_ANSWERED, update);
}

NetStream Info Returning 0's (Icecast Stream)

I've searched high and low for a fix to this issue, but cannot find ANYTHING on why almost all the properties are being returned as 0.
I am using FLV wrapping to pull a live audio stream from Icecast (since Adobe, 15 years later, still haven't fixed their live audio memory leak issue). It works great, everything functions perfectly.
However, I'm wanting to create a bandwidth monitor (for my iPhone port, and for my normal Flash player)... But whenever I retrieve netStreamInfo it returns as 0! For dataBytesPerSecond, audioBytesPerSecond, byteCount, dataByteCount, nearly EVERY SINGLE PROPERTY returns 0. I have this run on a 1-second timer.
Here's the total info output:
currentBytesPerSecond=0
byteCount=0
maxBytesPerSecond=0
audioBytesPerSecond=0
audioByteCount=0
videoBytesPerSecond=0
videoByteCount=0
dataBytesPerSecond=0
dataByteCount=0
playbackBytesPerSecond=16296.296296296296
droppedFrames=0
audioBufferLength=0.072
videoBufferLength=0
dataBufferLength=0
audioBufferByteLength=1540
videoBufferByteLength=0
dataBufferByteLength=0
srtt=0
audioLossRate=0
videoLossRate=0 Data Bytes Per Second
That output was about 5 minutes in. I noted the playBackBytesPerSecond never changed, and the audioBufferByteLength liked to switch between 1540 and 23xx randomly.
Can anyone pleaaase help me out here?
My actionscript:
package
{
import flash.display.Sprite;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.events.NetStatusEvent;
import flash.utils.Timer;
import flash.media.Sound;
import flash.net.URLRequest;
import flash.media.SoundChannel;
import flash.media.SoundMixer;
import flash.media.SoundTransform;
import flash.display.Loader;
import flash.errors.IOError;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.net.NetStreamInfo;
import flash.utils.ByteArray;
import flash.media.*
public class soundContainer extends Sprite
{
public var slider:SliderMC = new SliderMC();
private var _video:Video;
private var _stream:NetStream;
private var _playbackTime:TextField;
private var _duration:uint;
private var _timer:Timer;
private var _soundChannel:SoundChannel;
public var audioTransform:SoundTransform = new SoundTransform();
public var _URL:String;
public var flvUrl:String = "s";
public var dragging:Boolean = false;
public var rectangle:Rectangle = new Rectangle(0,0,100,0);
private var ba:ByteArray;
private var bn;
public function soundContainer() {
addEventListener(Event.ADDED_TO_STAGE, init);
}
public function init(e:Event):void
{
ba = new ByteArray();
slider.x = 73.85;
slider.y = 10.95;
addChild(slider);
slider.slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, dragIt);
stage.addEventListener(MouseEvent.MOUSE_UP, dropIt);
_timer = new Timer(1000);
_timer.addEventListener(TimerEvent.TIMER, onTimer);
_timer.start();
}
public function dragIt(e:MouseEvent):void
{
slider.slider_mc.startDrag(false, rectangle);
dragging = true;
slider.slider_mc.addEventListener(Event.ENTER_FRAME, adjustVolume);
}
public function dropIt(e:MouseEvent = null):void
{
if (dragging)
{
slider.slider_mc.stopDrag();
dragging = false;
}
}
public function adjustVolume(e:Event):void
{
var vol:Number = slider.slider_mc.x / 100;
var st:SoundTransform = new SoundTransform(vol);
SoundMixer.soundTransform = st;
}
public function playMyFlv(flvUrl)
{
_URL = flvUrl;
_video = new Video();
var connection:NetConnection = new NetConnection();
connection.connect(null);
_stream = new NetStream(connection);
_stream.soundTransform = audioTransform;
_stream.play(flvUrl);
var Client:Object = new Object();
_stream.client = Client;
_video.attachNetStream(_stream);
addChild(_video);
}
public function stopMyFlv()
{
SoundMixer.stopAll();
trace("stop");
try
{
_stream.close();
}
catch (error:IOError)
{
}
}
private function onNetStatus(e:NetStatusEvent)
{
}
private function onTimer(t:TimerEvent):Number
{
trace(_stream.info + " Data Bytes Per Second");
}
public function onIOError(e:IOError)
{
trace("Failed to load");
}
}
}

Getting data from custom classes (an OOP question)

How can I get some var / data from a custom classes?
The XML class
package classes
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
public class videoData extends MovieClip
{
private var myXML:XML;
private var myXMList:XMLList;
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
private function processXML(e:Event):void
{
myXML = new XML(e.target.data);
myXMList = new XMLList(myXML.children());
}
public function getXML()
{
return myXML;
}
}
}
The class that is calling the XML
package classes
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import classes.videoData;
public class playList extends MovieClip
{
private var vData:videoData = new videoData();
public function playList()
{
trace(vData.getXML())
}
}
}
I would setup an event listener in 'playList' and dispatch an Event from 'videoData' once the XML has finished loading. That way you know when it's finished loading without using ENTER_FRAME (which will use alot more CPU as its checking every frame).
package classes
{
import flash.events.*;
import flash.display.MovieClip;
import classes.VideoData;
public class PlayList extends MovieClip
{
private var vData:VideoData;
public function PlayList()
{
vData = new VideoData();
vData.addEventListener(Event.COMPLETE, onXMLCompleteHandler);
}
private function onXMLCompleteHandler(e:Event):void
{
vData.removeEventListener(Event.COMPLETE, onXMLCompleteHandler);
trace(vData.getXML());
}
}
}
package classes
{
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.events.Event;
import flash.display.MovieClip;
public class VideoData extends MovieClip
{
private var myXML:XML;
private var myXMList:XMLList;
private var myXMLLoader:URLLoader;
public function VideoData()
{
myXMLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
private function processXML(e:Event):void
{
myXMLLoader.removeEventListener(Event.COMPLETE, processXML);
myXML = new XML(e.target.data);
myXMList = new XMLList(myXML.children());
dispatchEvent(e);
}
public function getXML():XML
{
return myXML;
}
}
}
You should also ALWAYS capitalise your class names 'VideoData' not 'videoData'
You will need for the XML data to have been received before getting a value.
Add a private Boolean _xmlLoaded in your videoData class , set it to true in the processXML method.
Create a getter
public function get xmlLoaded():Boolean
{
return _xmlLoaded;
}
Now you can do this:
private var data:videoData = new videoData();
private var xmlData:XML;
private function init():void
{
addEventListener(Event.ENTER_FRAME , xmlLoaded );
}
private function xmlLoaded(event:Event):void
{
if( videoData.xmlLoaded )
{
xmlData = videoData.getXML();
removeEventListener(Event.ENTER_FRAME , xmlLoaded );
}
}
You are already getting your private myXML variable out through the .getXML() method. This is the best way to expose encapsulated data to outside classes.
An alternative would be to make your myXML field public instead of private, but using the get/set accessor methods you are hiding your actual implementation from outside world.
[Edit]
If your getXML() method is returning null, it means that your event handler (the processXML method) has not yet been called.
The problem appears to be in your VideoData constructor:
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.load(new URLRequest("playlist.xml"));
myXMLLoader.addEventListener(Event.COMPLETE, processXML);
}
The XML file is probably loaded before you attach the event handler, and that is why the event fires right before you start to listen to it. Try to reverse it and see if it works:
public function videoData()
{
var myXMLLoader:URLLoader = new URLLoader();
myXMLLoader.addEventListener(Event.COMPLETE, processXML); // moved up
myXMLLoader.load(new URLRequest("playlist.xml"));
}