onMetaData never called for MP3 streaming - actionscript-3

I am streaming a MP3 resource using NetStream in Flash.
To display the progress of the song I need the duration of the song.
But onMetaData is never being called for the NetStream object.
Here's the code http://pastebin.com/VZvdqTF5
Update: seems like the MP3 resource does not provide necessary MetaData for the MP3 resource. So this is not the problem with the code, it has something to do with the streaming server I am using in the application.

Be sure that you are setting the client propriety of the NetStream class.
client property: Specifies the object on which callback methods are invoked to handle
streaming or F4V/FLV file data. The default object is this, the
NetStream object being created. If you set the client property to
another object, callback methods are invoked on that other object. The
NetStream.client object can call the following functions and receive
an associated data object: onCuePoint(), onImageData(), onMetaData(),
onPlayStatus(), onSeekPoint(), onTextData(), and onXMPData().
yourNetStreamInstance.client = {onMetaData:onMetaData};
function onMetaData(metaData:Object):void
{
trace(metaData.duration); // duration
}

ns.client = new ConnectionClient(this);
Define that class inside of your NetStream class at the bottom
class ConnectionClient {
private var _owner:YourNSStreamObjectClass;
public function ConnectionClient(owner:YourNSStreamObjectClass) : void {
_owner = owner;
}
public function onMetaData(info : Object) : void {
//_owner.setMetaData(info);
}
public function onCuePoint(info : Object) : void {
//trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
}
public function onXMPData(info : Object) : void {
//trace("xmp data = " + info);
}
public function onPlayStatus(info : Object) : void {
//trace("onPlayStatus data = " + info);
}
}

Related

[AS3]How can I casting AObject to BObject automatically?

I want to cast AObject to BObject automatically like toString().
My original code is below:
var a:AObject = new AObject();
var b:BObject = new BObject();
someFunction(b:BObject):void{}
someFunction(a.toBObject()); // no error
trace(a.toString()); //[object AObject]
So, I want to finish it like toString()
someFunction(a); //TypeError: Error #1034: Type Coercion failed
trace(a); //[object AObject]
How can I solve it?
If you are wanting to pass two arbitrary objects that might be handled similarly, you can use interfaces to "hide" the differences and expose the seemingly shared functionality. I'm not saying this is good practice for your situation, but it is a solution. As in...
public interface CommonGround
{
function toString() : String;
}
public class AObject implements CommonGround
{
public function toString() : String
{
// implement here
}
}
public class BObject implements CommonGround
{
public function toString() : String
{
// implement here
}
}
...and then use them elsewhere in the program...
public someFunction( obj:CommonGround ) : void
{
trace( obj.toString() );
}
...or...
var obj:CommonGround = new AObject();
trace( obj.toString() );

binding device image path windows phone 8.1

How to bind device image path windows phone.
Below is image path
"C://Data//Users//Public//Pictures//Camera Roll//WP_20141001_002.jpg"
Thanks
I'm not sure if in your case using string is a good choice - maybe it will be possible to use BitmapImage - obtain a StorageFile from path, open Stream and then set BitmapImage - in this case you perform async operations outside converter.
In case you still want to use string it's possible, but will need some special approach - using async methods along with binding. There is a very good article about aynchronous MVVM, written by Stephen Cleary. Basing on the article and other Stephen's answer I've made such a code:
First of all, we will have to define a Converter - it's little complicated as getting file and stream is asynchronous:
/// <summary>
/// Converter getting an image basing upon delivered path
/// </summary>
public class PathToImage : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var task = GetImage((String)value);
// the below class you will find in Stephen's answer mentioned above
return new TaskCompletionNotifier<BitmapImage>(task);
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{ throw new NotImplementedException(); }
private async Task<BitmapImage> GetImage(string path)
{
StorageFile file = await StorageFile.GetFileFromPathAsync(path);
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
BitmapImage image = new BitmapImage();
image.SetSource(stream);
return image;
}
}
}
In our page we will need a property, which we will use in binding and set the DataContext:
public sealed partial class MainPage : Page, INotifyPropertyChanged
{
private string imagePath;
public string ImagePath
{
get { return imagePath; }
set { imagePath = value; RaiseProperty("ImagePath"); }
}
public MainPage()
{
this.InitializeComponent();
DataContext = this;
}
// rest of the code
Of course we have to define our binding - for example in XAML, it's little tricky as first we have to bind the DataContext to our Task then bind Source to the Result, which will be raised as the image is loaded:
<Image DataContext="{Binding ImagePath, Converter={StaticResource PathToImage}}" Stretch="Uniform"
Source="{Binding Result} HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
Once we have this all, we can set the property like this:
ImagePath = #"C:\Data\Users\Public\Pictures\Camera Roll\WP_20141001_002.jpg";
and we should see the result on the screen.

win8 Frame delegate

I have a frame which has a function that updates the frame when an event in another class is raised.
I have the class 'IRCClient' and 'MainFrame'. The IRCClient class has an event 'OnMessageRecvd', the MainFrame has a function 'HandleNewMessageReceived'. In the MainFrame class I have the variables 'CurrentServer' and 'CurrentChannel' to indicate what channel on what server is currently shown to the user.
Now, when I set the 'CurrentServer' and 'CurrentChannel' in the callback of a button, they have a value and all is fine. However, when the 'HandleNewMessageReceived' function is called by the 'OnMessageRecvd' event of IRCClient, the CurrentServer and CurrentChannel are both equal to any value (null) stated in the constructor of MainFrame.
Does anyone have an idea what the source of this behavior is? Thanks a lot in advance.
EDIT:
Below is the code, I've only posted the code in question (any function that uses the CurrentChannel and CurrentServer properties) and snipped away unrelated code.
// Main page, shows chat history.
public sealed partial class MainPage : LIRC.Common.LayoutAwarePage
{
private uint maxMessages;
IRCClient ircc;
IRCHistory irch;
string CurrentServer, CurrentChannel;
// Does all the setup for this class.
public MainPage()
{
this.InitializeComponent();
ircc = App.ircc; // This is a global variable in the 'App' class.
ircc.OnMessage += NewMessageReceived;
irch = App.irch; // This is also a global variable in the 'App' class.
currentChannel = currentServer = null;
}
// Restores the previous state.
protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
{
if (pageState != null)
{
if(pageState.ContainsKey("viewedChannel"))
{
// Retrieve required info.
string[] viewedChannelTokens = (pageState["viewedChannel"] as string).Split('.');
CurrentChannel = viewedChannelTokens[0];
CurrentServer = viewedChannelTokens[1];
// If the saved channel or server got corrupt
if (string.IsNullOrEmpty(CurrentChannel) || string.IsNullOrEmpty(CurrentServer))
{
// Check if a channel is open, if so, select it.
*snip* // Non-relevant code.
}
// Clear and load required history.
ClearHistory();
if(CurrentServer != null && CurrentChannel != null)
LoadHistory(CurrentServer, CurrentChannel);
}
}
// Create buttons that switch to a channel
*Snip* // Calls AddChannelButton
}
// Creates a button that, when clicked, causes the ChatHistoryView to display the ChannelHistory.
void AddChannelButton(string Server, string Channel)
{
Button btn = new Button();
btn.Content = Channel + "\n" + Server;
btn.Width = 150;
// A function to switch to another channel.
btn.Click += (e, s) =>
{
ClearHistory(); // Clears the ChatHistoryVi.ew field.
LoadHistory(Server, Channel); // Does the actual loading of the channel history
CurrentChannel = Channel;
CurrentServer = Server;
};
ChannelBar.Children.Add(btn);
}
// The function that is called by the IRCClient.OnMessageRecv event.
public void NewMessageReceived(ref DataWriter dw, IRCServerInfo ircsi, IRCClient.RecvMessage recvmsg)
{
if (ircsi.Name == CurrentServer && CurrentChannel == recvmsg.recipient)
{
AddMessage(DateTimeToTime(DateTime.UtcNow), recvmsg.author, recvmsg.message);
}
}
}
// Responsible for creating, managing and closing connections.
public class IRCClient
{
// A structure that describes a message.
public struct RecvMessage
{
public string author; // Nickname
public string realName;
public string ipAddress;
public string recipient; // Indicates in what channel or private converstion.
public string message; // The actual message
};
// Describes how a function that handles a message should be declared.
public delegate void MessageHandler(ref DataWriter dw, IRCServerInfo ircsi, RecvMessage msg);
// Gets raised/called whenever a message was received.
public event MessageHandler OnMessage;
}
It's not clear what is happening from what you said, but if the variables are set to the values you set in the constructor when you check them - it means that either you have not changed them yet by the time you are expecting them to be changed or you set the value of some other variables instead of the ones you thought you had.
These are only guesses though and you can't expect more than guesses without showing your code.

Type preservation failing with RemoteClass

Consider the following example dataclass:
[RemoteClass]
public class SOTestData {
public var i:int;
public function SOTestData(i:int) {
this.i = i;
}
}
As I understand, the RemoteClass metadata-tag should ensure that when an object of this class gets sreialized, the type information is preserved.
I used the following program to test:
public class SOTest extends Sprite {
public function SOTest() {
var data:SharedObject = SharedObject.getLocal("SOTest");
if (data.data.object) {
try {
var stored:SOTestData = data.data.object;
trace(stored.i);
} finally {
data.clear();
}
}
else {
data.data.object = new SOTestData(15);
data.flush();
}
}
}
Here the first run writes the data, seconds reads and clears. Running this, I still get a class cast error. Indeed, in the SharedObject there is no type information stored.
I don't think i'm using the metadata wrong, could it maybe be that the compiler doesn't know what to do with it? I don't get any compiler errors/warnings, although when i use some inexistant tag it doesn't complain either. I'm using Flex 4.6 SDK with FlashDevelop as IDE.
EDIT:
Below is the shared object. As you can see, the type is saved as "Object" instead of the actual type.
so = [object #2, class 'SharedObject'] {
data: [object #0, class 'Object'] {
object: [object #1, class 'Object', dynamic 'False', externalizable 'False'] {
i: 15,
},
}
}
I've only used RemoteClass for making AMF RemoteObject calls; I didn't think it had anything to do w/ Shared Objects. Per the docs
Use the [RemoteClass] metadata tag to register the class with Flex so
that Flex preserves type information when a class instance is
serialized by using Action Message Format (AMF). You insert the
[RemoteClass] metadata tag before an ActionScript class definition.
The [RemoteClass] metadata tag has the following syntax:
As best I can tell from the code you provided, you are not serializing the object in AMF format.
I believe your class cast error is due to the fact that you aren't casting your class. Shared Objects always come back as generic Objects. Try this:
var stored:SOTestData = data.data.object as SOTestData ;
Here is some code from an application I use. First the value object which will get serialized in a shared object:
package com.login.vos
{
[RemoteClass(alias="com.login.vos.UserVO")]
public class UserVO
{
public function UserVO()
{
}
public var firstName :String;
public var lastName :String;
public var userID :Number;
}
}
The the code to save the object:
public static function saveUserVO(userVO:UserVO):void{
var userSharedObject :SharedObject = SharedObject.getLocal('userVO') ;
userSharedObject.data.userVO = userVO;
userSharedObject.flush();
}
And finally, the code to load the objecT:
public static function getUserVO():UserVO{
var userSharedObject :SharedObject = SharedObject.getLocal('userVO')
if(userSharedObject.size <=0){
return null;
}
return userSharedObject.data.userVO as UserVO;
}
The only obvious difference between this and the code by the original poster is that I'm specifying an alias in the RemoteClass metadata.

Enable WCF Data Service to accept/return JSON by default

I have a WCF Data Service that I'd like to return JSON by default for all operations. Is there a place I can set that in configuration/via service attributes?
In order to enable json via the $format tag like this:
host:8038/YourService.svc/?$format=json
Add this attribute to your service declaration:
[JSONPSupportBehavior]
public class Service : DataService<YourEntities>
Add this as a class to your service:
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Text;
using System.Xml;
namespace YourNamespaceHere.Service
{
public class JSONPSupportInspector : IDispatchMessageInspector
{
// Assume utf-8, note that Data Services supports
// charset negotation, so this needs to be more
// sophisticated (and per-request) if clients will
// use multiple charsets
private static Encoding encoding = Encoding.UTF8;
#region IDispatchMessageInspector Members
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
if (request.Properties.ContainsKey("UriTemplateMatchResults"))
{
HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
UriTemplateMatch match = (UriTemplateMatch)request.Properties["UriTemplateMatchResults"];
string format = match.QueryParameters["$format"];
if ("json".Equals(format, StringComparison.InvariantCultureIgnoreCase))
{
// strip out $format from the query options to avoid an error
// due to use of a reserved option (starts with "$")
match.QueryParameters.Remove("$format");
// replace the Accept header so that the Data Services runtime
// assumes the client asked for a JSON representation
httpmsg.Headers["Accept"] = "application/json";
string callback = match.QueryParameters["$callback"];
if (!string.IsNullOrEmpty(callback))
{
match.QueryParameters.Remove("$callback");
return callback;
}
}
}
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (correlationState != null && correlationState is string)
{
// if we have a JSONP callback then buffer the response, wrap it with the
// callback call and then re-create the response message
string callback = (string)correlationState;
XmlDictionaryReader reader = reply.GetReaderAtBodyContents();
reader.ReadStartElement();
string content = JSONPSupportInspector.encoding.GetString(reader.ReadContentAsBase64());
content = callback + "(" + content + ")";
Message newreply = Message.CreateMessage(MessageVersion.None, "", new Writer(content));
newreply.Properties.CopyProperties(reply.Properties);
reply = newreply;
}
}
#endregion
class Writer : BodyWriter
{
private string content;
public Writer(string content)
: base(false)
{
this.content = content;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("Binary");
byte[] buffer = JSONPSupportInspector.encoding.GetBytes(this.content);
writer.WriteBase64(buffer, 0, buffer.Length);
writer.WriteEndElement();
}
}
}
// Simply apply this attribute to a DataService-derived class to get
// JSONP support in that service
[AttributeUsage(AttributeTargets.Class)]
public class JSONPSupportBehaviorAttribute : Attribute, IServiceBehavior
{
#region IServiceBehavior Members
void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.MessageInspectors.Add(new JSONPSupportInspector());
}
}
}
void IServiceBehavior.Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
}
}
You could add an extension as per this download.
http://archive.msdn.microsoft.com/DataServicesJSONP
You would still need to customise it as the code is checking to see if you are asking for JSON formatting via the URL.e.g $format=json.