Flex: how to change the volume of an EMBEDDED sound? - apache-flex

Searching for how to change the volume of sounds, I always get this irritating snd=new Sound(URLRequest), followed by snd.setVolume(val). Oh, fine, but my sound is not an URLRequest, it's an embed.
I've made a lot of random attempts (1) to no avail. How am I supposed to do that instead?
(1) including casting my class to Sound, creating a Sound with the embed class as argument, creating a SoundTransform and setting it to the channel, etc.

Instantiate your embedded class like this:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var smallSound:Sound = new soundClass() as Sound;
var trans:SoundTransform = new SoundTransform(.01);
smallSound.play(0,0,trans);
}
Update:
In case what you really wanted to know was how to change the volume if the sound was already playing:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
public var smallSound : Sound;
public var vol : Number = 0.01;
public var trans : SoundTransform;
public var chan : SoundChannel = new SoundChannel();
protected function application1_creationCompleteHandler(event:FlexEvent):void {
smallSound = new soundClass() as Sound;
trans = new SoundTransform(vol);
chan = smallSound.play(0,0,trans);
}
protected function volUp_clickHandler(event:MouseEvent):void {
vol += .1;
trans = new SoundTransform(vol);
chan.soundTransform = trans;
}

Related

How to play several sounds one by one in flex

I have several sounds, how can I play them one by one. When I just use play(), the sounds play simultaneously. I also tried to handle SOUND_COMPLETE event, but it doesn't work.
sampleMP3A.play().addEventListener(
Event.SOUND_COMPLETE,
function(event:ResultEvent, o:Object):void {
sampleMP3B.play();
});
sampleMP3A plays well, but sampleMP3B doesn't play.
private var sounds:Array // it contain your sounds.
private var ind:Number = 0;
private function playSounds():void
{
var req:URLRequest = new URLRequest(sounds[ind]);
var s:Sound = new Sound(req);
var soundChannel:SoundChannel = new SoundChannel;
soundChannel = s.play();
soundChannel.addEventListener(Event.SOUND_COMPLETE,onComplete);
}
private function onComplete(event:Event):void
{
ind++;
playSounds();
}

AdvancedDatagrid GroupingCollection in AS3

My AIR-Application is based on Mate.
I receive Data from a SQLite and put the Date into a ArrayCollection.
In the class of my AdvancedDataGrid, i create a GroupingCollection via mxml. All works fine.
I prefer to build the GroupingCollection in Actionscript. But i can't find anything, how to code this.
In the adobe help itself, they create a GroupingCollection in mxml.
The goal is, to instanciate the gc in model of mate for another class. This will be a chart and the dataProvider must be the gc.
Another Idea is, to build the groupingCollection and put it into the model via two-way-bindung. But I'm not sure, if this will work.
Have you any hint for me?
Thank you
Frank
It works like this. What a fight.
private function onCreationComplete () :void
{
adg.dataProvider = createDataProvider();
}
private function createDataProvider () :GroupingCollection2
{
var tmp:GroupingCollection2 = new GroupingCollection2();
tmp.source = dpArrColl;
tmp.grouping = adgGrouping();
tmp.refresh(false);
return tmp;
}
private function adgGrouping () : Grouping
{
var tmp:Grouping = new Grouping();
tmp.fields = [groupingFieldArray()];
return tmp;
}
private function groupingFieldArray () :GroupingField
{
var tmp:GroupingField = new GroupingField();
tmp.name = "groupName1";
tmp.summaries = [adgSummaries()];
return tmp;
}
private function adgSummaries () : SummaryRow
{
var tmp:SummaryRow = new SummaryRow();
tmp.summaryPlacement = "group";
tmp.fields = [adgSummaryFiled1(), adgSummaryField2()];
return tmp;
}
private function adgSummaryFiled1 () :SummaryField2
{
var tmp:SummaryField2 = new SummaryField2();
tmp.dataField = "Sumfiel1";
tmp.summaryOperation = "SUM";
return tmp;
}
private function adgSummaryField2 () : SummaryField2
{
var tmp:SummaryField2 = new SummaryField2();
tmp.dataField = "Sumfield2";
tmp.summaryOperation = "COUNT";
return tmp;
}
I hope, someone will help this someday.
BR
Frank

FileReference and registerClassAlias

I'm trying to use the native flex serialization/deserialization process to save/load state of a workspace in flex. In order to save or load a file I have to use my servlet, which just bounces back the bytes from the input stream to the output stream. Here's a basic outline of my Flex code:
Serialized Object Container:
public class MyWorkspace {
public var id : String;
public var url : String;
public var objectCollection : ArrayCollection; // Contains MySubObjects
}
Serialized sub object:
public class MySubObject
{
public var name:String;
public var csv:String;
}
Visual Element Constructor:
public function VisualSandbox(){
registerClassAlias("MyWorkspaceAlias", MyWorkspace);
registerClassAlias("MySubObjectAlias", MySubObject);
}
Visual Element Event Handlers:
public function onSaveButtonClick(event : MouseEvent) : void
{
var ws : MyWorkspace = new MyWorkspace();
ws.id = "ID";
ws.url = "URL";
ws.objectCollection = new ArrayCollection(veObjCollectionAC.source.slice());
var ba : ByteArray = new ByteArray();
ba.writeObject(ws);
ba.position = 0;
var fr : FileReference = new FileReference();
// There's no need for me to put the rest so
...
fr.download(urlRequest, "workspace.ws");
}
public function onLoadButtonClick(event : MouseEvent) : void
{
veFileReference = new FileReference();
veFileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, loadCompleteHandler);
// This part works as well so I'm skipping it.
}
public function loadCompleteHandler(event : DataEvent) : void
{
// Pretend I loaded "workspace.ws" by bouncing it off of my servlet byte for byte.
var ba : ByteArray = new ByteArray();
ba.writeObject(event.data);
ba.position = 0;
var obj : * = ba.readObject();
trace(obj is MyWorkspace); // Prints false
}
So my problem here is not with the saving of the workspace. That works great. My problem is with the loading of a workspace. The event.data that I write to the byte array is not reconstituted into a MyWorkspace object even though it is exactly what I wrote to the file.
There has to be a way of making a MyWorkspace object from the data, but I can't figure it out. Has anyone tried to do this before?
Thanks!
I've figured out what the problem here is. It specifically has to do with the line:
ba.writeObject(event.data);
The data field of the event, being a DataEvent, is specifically of type String. ByteArray.writeObject() puts a type code at the beginning of the byte array. This took me many hours of looking at Hexplorer to figure out why, exactly, the byte array had 2-3 extra characters at its beginning.
My current best solution for this is to change that line as follows:
for (var i : int = 0; i < event.data.length; ++i)
{
ba.writeByte(event.data.charCodeAt(i));
}
This ensures that the byte array is exactly the same as what was saved to my local drive and bounced off my servlet.
After doing this, trace(obj is MyWorkspace) prints true.
Hope this helps someone else in the future!
Have you tried casting the value?
var obj : MyWorkspace = ba.readObject() as MyWorkspace;

Pause and resume download in flex?

Is it possible in an air application to start a download, pause it and after that resume it?
I want to download very big files (1-3Gb) and I need to be sure if the connection is interrupted, then the next time the user tries to download the file it's start from the last position.
Any ideas and source code samples would be appreciated.
Yes, you would want to use the URLStream class (URLLoader doesn't support partial downloads) and the HTTP Range header. Note that there are some onerous security restrictions on the Range header, but it should be fine in an AIR application. Here's some untested code that should give you the general idea.
private var _us:URLStream;
private var _buf:ByteArray;
private var _offs:uint;
private var _paused:Boolean;
private var _intervalId:uint;
...
private function init():void {
_buf = new ByteArray();
_offs = 0;
var ur:URLRequest = new URLRequest( ... uri ... );
_us = new URLStream();
_paused = false;
_intervalId = setInterval(500, partialLoad);
}
...
private function partialLoad():void {
var len:uint = _us.bytesAvailable;
_us.readBytes(_buf, _offs, len);
_offs += len;
if (_paused) {
_us.close();
clearInterval(_intervalId);
}
}
...
private function pause():void {
_paused = true;
}
...
private function resume():void {
var ur:URLRequest = new URLRequest(... uri ...);
ur.requestHeaders = [new URLRequestHeader("Range", "bytes=" + _offs + "-")];
_us.load(ur);
_paused = false;
_intervalId = setInterval(500, partialLoad);
}
if you are targeting mobile devices, maybe you should take a look at this native extension: http://myappsnippet.com/download-manager-air-native-extension/ it supports simultaneous resumable downloads with multi-section chunks to download files as fast as possible.

embedding a Movieclip with flashDevelop

I am trying to embed a movieClip with flashDevelop but apparently its not working because its not recognizing the movieclips that are within it. here is my code
package com.objects{
import flash.display.MovieClip
import flash.text.TextField;
import flash.events.*;
import flash.text.TextFormat;
[Embed(source='../../../lib/fighter.swf', symbol='InfoBox')]
public class InfoBox extends gameObject {
protected var textf:TextField;
protected var s:String;
public var type:Boolean = false;
private var letter:Number = 0;
private var string:Array;
private var line:Number = 0;
private var portNum:Array;
public function InfoBox():void
{
portNum = new Array();
portrait.stop();
x = 400;
y = 550;
string = new Array();
var format = new TextFormat();
format.size = 18;
textf = new TextField();
textf.width = 550;
textf.height = 85;
textf.x = -220;
textf.y = -60;
textf.wordWrap = true;
textf.defaultTextFormat = format;
addChild(textf);
contButton.addEventListener(MouseEvent.MOUSE_DOWN, StoryNext);
}
private function StoryNext(e:MouseEvent):void
{
if(string.length > 1)
{
portNum.splice(0,1);
string.splice(0,1);
trace(string.length);
letter = 0;
}
else
{
contButton.removeEventListener(MouseEvent.MOUSE_DOWN, StoryNext);
dispatchEvent(new Event("StoryContinue"));
}
}
public function textInfo(msg:String,num:Number = 1):void
{
string.push(msg);
portNum.push(num);
}
override public function updateObject():void
{
TypeWords();
}// End UpdateObject
public function TypeWords():void
{
if(type)
{
portrait.gotoAndStop(portNum[0]);
var s:String = string[0];
if(letter <= s.length)
{
textf.text = s.substring(0,letter);
}
letter++
}
}
}
}
and I am getting this error
C:\Users\numerical25\Documents\RealGames\FighterPilot\beta1FlashDev\src\com\objects\InfoBox.as(23): col: 4 Error: Access of undefined property portrait.
portrait is a movie clip that I have inside of the info box movie clip. it is already on the stage and i gave it a instance name of portrait. It worked in flash, but now its not in flashDevelop
Try accessing the childs by name. It should work.
(getChildByName("portrait") as MovieClip).gotoAndStop(portNum[0]);
You need to define the corresponding properties on your class. In this case you can add:
public var portrait:MovieClip;
If it's some other type, for instance a Sprite you can change the definition to that.
EDIT: If you're having trouble setting up Flash Develop, I wrote some tutorials on that
[Embed(source='../../../lib/fighter.swf',
symbol='InfoBox')]
I'd say use SWCs not SWFs, it will make it a ****load easier.
SWCs keep all the stuff in place, whereas the swf can remove assets that are not used to save room.
Also in your flash develop panel you will see the swc (like the swf) and see all the classes that are included. Just right-click on it and add it to library. You won't have to use the [embed] code.
give that a try first, unless you absolutely need an swf.
To create an swc, use the flash tab under publish settings.
you can add linkage name for your MovieClip and export it as SWC, suppose named "mymc"
then copy SWC file to you FD project.
in your code, just addChild(new mymc());

Resources