PDA

View Full Version : [2.2.x, 3.x] ux.Media.plugin.AudioEvents



hendricd
18 Sep 2009, 8:45 AM
Easily add audio (WAV/MP3) playback for any Ext.Component/Ext.Element events (eg. collapse, expand, resize, minimize, mouseover, etc).

Latest HTML5 Audio support is built-in, with fallback to Window Media Player plugin for browsers that don't support it.

Add audio support to Ext.MessageBox, a failed Ajax request, a chart event...
Give your entire layout Audio support with a single plugin instance.
Define a custom audio player if you wish as well.

Simply include the uxmedia.js file in your project, and define what audio streams you'd like to play for any event:




var audio = new Ext.ux.Media.plugin.AudioEvents({
audioEvents :{
beforecollapse : 'demos/media/audio/Utopia Restore Down.WAV',
beforeexpand : 'demos/media/audio/Utopia Restore Up.WAV',
beforeclose : 'demos/media/audio/Utopia Windows Exit.WAV',
mouseover : 'demos/media/audio/Utopia Question.WAV'
},
volume : .7
});

new Ext.Panel({
title : 'Test'
autoHeight : true,
width : 400,
contentEl : 'startingout'
plugins : audio,
listeners : {
afterrender : function(panel){
this.audioPlugin.init( panel.body.child('img') ); //add mouseover audio event to an Ext.Element
}
}
});

//To quiet things down:
audio.disable()
//or
audio.setVolume(.2);

A more elaborate online demonstration is available here (http://demos.theactivegroup.com/?demo=media&script=audioev).

mystix
18 Sep 2009, 10:18 AM
you da media man!! =P~

jay@moduscreate.com
23 Sep 2009, 5:38 AM
aww man this is HOT!!

Nash-T
24 Sep 2009, 11:34 AM
Nice one.
Do you think this can be used to attach unique audio help files to individual tabs/buttons to augment the tooltips?

This is going on my todo list.

Thanks!
-Tim

hendricd
24 Sep 2009, 11:45 AM
Nice one.
Do you think this can be used to attach unique audio help files to individual tabs/buttons to augment the tooltips?

This is going on my todo list.

Thanks!
-Tim

Now your thinking like an 'audiovox'! ;)

For tabPanel:



var audioClass = Ext.ux.Media.plugin.AudioEvents;
....
{xtype : 'tabpanel',
plugins: new audioClass({
audioEvents :{
tabchange : 'demos/media/audio/swish.WAV',
},
volume : .4
});
For a Button( anything that publishes an event) :



new audioClass({
audioEvents :{
click : 'demos/media/audio/swish.WAV',
},
volume : .5
}).init(someButtonComponent);For the global tooltip:



if(Ext.QuickTips.getQuickTip()){
new audioClass({
audioEvents :{
show: 'demos/media/audio/swish.WAV',
},
volume : .5
}).init( Ext.QuickTips.getQuickTip() );
}

Dumbledore
24 Sep 2009, 11:39 PM
Wow... really nice!

What kind of mp3 is supported? I have problems to play 128k MP3s...

And it seems there is a problem when using this with the Ext.ux.Livegrid. When i load uxmedia.js there is an error when displaying a new livegrid:

B(D, "mask") is undefined

Bye

hendricd
25 Sep 2009, 12:03 AM
What kind of mp3 is supported? I have problems to play 128k MP3s...


Widest CODEC support on recent HTML5-Compatible browsers is for WAV, OGG, and mp3. But for all browsers, it ultimately depends on what the default audio player defined for use by the browser is (for those media types). I chose WAV because it generally enjoys the most cross-browser support (think Window Media Player and QuickTime).



And it seems there is a problem when using this with the Ext.ux.Livegrid. When i load uxmedia.js there is an error when displaying a new livegrid:

B(D, "mask") is undefined


Have no idea. What Ext version you running all this on?
Might check with LiveGrid's author.

Dumbledore
25 Sep 2009, 12:36 AM
i am running Ext 3.0.2...

Must i defined special things for using mp3 or did your component automaticly switch between wav or mp3?

The error with the live grid only occurs when using a loadmask. I will try to find the reason for this.

[update]

The reason is the overwriting for Ext.Element.mask in uxmedia.js...

hendricd
25 Sep 2009, 12:47 AM
i am running Ext 3.0.2...

Must i defined special things for using mp3 or did your component automaticly switch between wav or mp3?

The error with the live grid only occurs when using a loadmask. I will try to find the reason for this.

Again, that depend on what audio plugins/controls are installed on your browser(s). What are you running and versions?

Dumbledore
25 Sep 2009, 12:57 AM
i am running Firefox 3.5.3

hendricd
25 Sep 2009, 1:43 AM
i am running Firefox 3.5.3


OK. Firefox 3.5 has HTML5 audio support.
With uxmedia.js loaded in your page, open up Firebug console.

Type
Ext.capabilities.hasAudio.mp3or just browse the entire hasAudio block:

Ext.capabilities.hasAudioWhat's it say? If mp3 is false, no dice! If true, then define an mp3 file for one of the events and see if it plays it. If not compatible/supported, you'll hear nothing (but your own moan of dissapointment).

Dumbledore
25 Sep 2009, 2:13 AM
ok, there is the reason.

my Firefox-Configuration has no support for playing mp3. The first time i read about your component i thought this is a replacement for soundserver2...

Sorry about that...

aw1zard2
25 Sep 2009, 2:05 PM
Just an FYI for others who might not know...

Firefox 3.5 HTML5 audio only supports the following...


Note: Currently, Gecko supports only Vorbis, in Ogg containers, as well as WAV format. Also, the server must serve the file using the correct MIME type in order for Gecko to play it correctly.

https://developer.mozilla.org/En/HTML/Element/Audio

=)

billprince
26 Apr 2010, 9:09 PM
Awesome´╝üThank you for your donate!

saadkhan
13 Jun 2010, 1:21 AM
The link to demo isnt working......please can anyone provide a sample of this?

hendricd
15 Jun 2010, 5:13 PM
Demo site is back online.

Example of what?

Bucs
17 Jun 2010, 10:29 AM
Doug, I need to play an audio file on panel load or click of a button. Audio file will be a lot longer than a quick chime or ding...maybe minute or two (audio instructions). Two questions:

1) is the AudioEvents the control to use, or ux.Media?
2) what is the best format to use for the audio file in your opinion (speed, size, clarity, etc.)

Thanks yet again :)

UPDATE: Nevermind on this one...was a little confused on where the Audio functionality was. I see that it is included in the ux.Media component.

hendricd
27 Jun 2010, 1:10 PM
@Bucs --OK, back in groove... ;)

I've just completed some work on 1.1 of the AudioEvents plugin (see attachment below -- simply include it anywhere AFTER uxmedia.js on your page).

Some new features:

- the Plugin itself can be rendered as a ux.Media.Component anywhere, so setting the controls:true config option will render either:

* an HTML5 Audio control in the container, or
* render whatever is configured as the fallback mediaCfg ( thinking IE).

- You can now stop/pause/play longer running audio streams via accessor methods provided by the plugin to Component the plugin is installed onto:




var plugin = new Ext.ux.Media.plugin.AudioEvents({
controls : true,
audioEvents :{
beforeshow : 'demos/media/audio/introduction_speach.WAV'
}
});

var tutor = new Ext.Panel({
autoHeight : true,
title : 'Audible Tutorial',
plugins : [plugin],
items : [
{xtype : 'panel', autoHeight : true, autoLoad : { url: 'assets/tutorial.htm'}},
plugin //the visible audio controls
]
}).show();
Bind these methods to Buttons/Toolbars if you like:


tutor.stopAudio();
tutor.playAudio();
tutor.pauseAudio();

The plugin will use HTML5 Audio support if availabe (and useNative is true ). The default fallback mediaCfg for browsers not supporting Audio object/tags is the ux.MediaCfg.mediaType:


{
mediaType : 'WAV',
start : false,
url : '',
}The plugin also provides HTML5 feature detection reports for Ext. See:


console.dir(
Ext.capabilities.hasAudio
);


An updated demo is available here: http://demos.theactivegroup.com/?demo=media&script=audioev


1) is the AudioEvents the control to use, or ux.Media? It can now support either role, it's just that the plugin is designed to easily wire up audio events to any event a component can fire.


2) what is the best format to use for the audio file in your opinion (speed, size, clarity, etc.) The real question is: what is the format your consumers likely have Audio support for !!
uxMedia provides several modern and legacy configurations for external players (Flash, QuickTime, Windows Media Player, etc) for use across many browsers. It's up to you to decide what players they are likely to have installed across all your target browsers. It may even be necessary to encode your media in more than one format to cover your top targets.

Bucs
27 Jun 2010, 1:29 PM
Awesome Doug, the Stop method will help me a ton, thanks so much.

Do you think an Event handler for a "complete" event on the AudioEvents will be possible (similar to the JWPlayer wrapper)?

Thanks again for all your community support Doug, you da man!

hendricd
27 Jun 2010, 1:52 PM
Do you think an Event handler for a "complete" event on the AudioEvents will be possible (similar to the JWPlayer wrapper)?


@Bucs -- In a word, no.
AudioEvents is design to work (degrading gracefully) across many browsers (HTML5-capable or not). What you seek would require that every Browser player handled a 'completed' event like that the same way.

If you need that level of support from all browsers, you'll need to stick with one player with a rich event system that will handle all the media codecs. JWPlayer is certainly one choice, and that's why I spent some time with a full-featured wrapper class for it alone (but it is, after all, Flash-based).

Bucs
29 Jun 2010, 11:03 AM
Doug, I am having a little difficulty understanding best way to implement the AudioEvents component. I have a control that simply displays content. If the controls 'audioUrl' config param is set on init, then that means the control should play an audio file that mimics the HTML content displayed. I was attaching the AudioEvents class up to the panel's after render event, but this seemed to conflict (IE only) with the afterrender listener that I am setting to display the HTML content. So, I am now thinking that I need to use the callback param of the load event (for the HTML content) to initiate and play the appropriate content.

Here is my control with relevant parts bolded:


AMD.Control.PanelContentTask = Ext.extend(Ext.Panel, {
/* ===================================================================================== */
// BEGIN: STATIC CONFIG PROPERTIES
id: 'pnlContentTask'
,title: 'Loading...'
,width: 610
,height: 355
,layout: 'form'
,frame: false
,iconCls: 'formColors'
,listeners : {
render: function (pnl) {
this.displayContent(pnl);

},
removed: function(cmp, ownCt) {

}
}


// END : STATIC CONFIG PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM PROPERTIES
, contentUrl: ''
, audioUrl : ''

// END : CUSTOM PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: COMPONENT INIT

, initComponent: function() {

// Setup title and content
if(this.inTitle != '') this.title = this.inTitle;
if(this.inContentUrl != '') this.contentUrl = this.inContentUrl;

// Build toolbar
var tb = new Ext.Toolbar({
items: [
{
xtype: 'tbfill'
},
{
id : 'btnProceed',
xtype : 'button',
text : 'Start Next Task Now',
iconCls : 'next',
disabled: false,
handler : this.markTaskComplete
}
]
});


// Setup Audio Events if audio parameter specified // was setting up AudioEvents in here, now just setting param
if(this.inContentAudioUrl != '')
{
this.audioUrl = this.inContentAudioUrl;

}

// Setup button bar buttons
this.bbar = tb;

AMD.Control.PanelContentTask.superclass.initComponent.call(this);

}

// END : COMPONENT INIT
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM METHODS


, displayContent: function(pnl){

// Perform Load
pnl.load({
url: this.contentUrl,
indicatorText: 'Please wait...',
text: 'Please wait...',
timeout: 30,
scripts: true,
callback: this.setupAudio(pnl)
//scope: yourObject, // optional scope for the callback
//nocache: false
});

pnlMgr = pnl.getUpdater();


}

, setupAudio: function(pnl){

if(Ext.capabilities.hasAudio && Ext.capabilities.hasAudio.wav){
//Give Ext.MessageBox Audio
alert('load WAV audio file now and play.');
}
else
{
if(Ext.capabilities.hasAudio && Ext.capabilities.hasAudio.mp3){
alert('load MP3 audio file now and play.');
}
else
{
alert('Attempt to play with a down-level plugin (probably IE)');
}
}


}

//................ other stuff .................


});

Ext.reg('x-mod-control-panelContenttask', AMD.Control.PanelContentTask);


the problem with this is that I no longer have the events to attach to as I want to play the audio file immediately in the callback. So does this mean I should just use the uxmedia to attempt to play the audio files? I realize this requires the flash plugin but at this point it might be the easiest thing to do.

If I don't do that, then I need to somehow instantiate the AudioEvents class inside those capability routines and play the correct file. I can have different versions, that's not a problem....but the problem is that I don't know how to pass the audioUrl to the AudioEvents class as I do not need to play the file upon an event instance, but rather I just need to play it NOW. The only way I see to pass the actual file to play is via an event listener in the config.

HELP?!

Bucs
29 Jun 2010, 11:04 AM
Doug, I am having a little difficulty understanding best way to implement the AudioEvents component. I have a control that simply displays content. If the controls 'audioUrl' config param is set on init, then that means the control should play an audio file that mimics the HTML content displayed. I was attaching the AudioEvents class up to the panel's after render event, but this seemed to conflict (IE only) with the afterrender listener that I am setting to display the HTML content. So, I am now thinking that I need to use the callback param of the load event (for the HTML content) to initiate and play the appropriate content.

Here is my control with relevant parts bolded:


AMD.Control.PanelContentTask = Ext.extend(Ext.Panel, {
/* ===================================================================================== */
// BEGIN: STATIC CONFIG PROPERTIES
id: 'pnlContentTask'
,title: 'Loading...'
,width: 610
,height: 355
,layout: 'form'
,frame: false
,iconCls: 'formColors'
,listeners : {
render: function (pnl) {
this.displayContent(pnl);

},
removed: function(cmp, ownCt) {

}
}


// END : STATIC CONFIG PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM PROPERTIES
, contentUrl: ''
, audioUrl : ''

// END : CUSTOM PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: COMPONENT INIT

, initComponent: function() {

// Setup title and content
if(this.inTitle != '') this.title = this.inTitle;
if(this.inContentUrl != '') this.contentUrl = this.inContentUrl;

// Build toolbar
var tb = new Ext.Toolbar({
items: [
{
xtype: 'tbfill'
},
{
id : 'btnProceed',
xtype : 'button',
text : 'Start Next Task Now',
iconCls : 'next',
disabled: false,
handler : this.markTaskComplete
}
]
});


// Setup Audio Events if audio parameter specified // was setting up AudioEvents in here, now just setting param
if(this.inContentAudioUrl != '')
{
this.audioUrl = this.inContentAudioUrl;

}

// Setup button bar buttons
this.bbar = tb;

AMD.Control.PanelContentTask.superclass.initComponent.call(this);

}

// END : COMPONENT INIT
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM METHODS


, displayContent: function(pnl){

// Perform Load
pnl.load({
url: this.contentUrl,
indicatorText: 'Please wait...',
text: 'Please wait...',
timeout: 30,
scripts: true,
callback: this.setupAudio(pnl)
//scope: yourObject, // optional scope for the callback
//nocache: false
});

pnlMgr = pnl.getUpdater();


}

, setupAudio: function(pnl){

if(Ext.capabilities.hasAudio && Ext.capabilities.hasAudio.wav){
//Give Ext.MessageBox Audio
alert('load WAV audio file now and play.');
}
else
{
if(Ext.capabilities.hasAudio && Ext.capabilities.hasAudio.mp3){
alert('load MP3 audio file now and play.');
}
else
{
alert('Attempt to play with a down-level plugin (probably IE)');
}
}


}

//................ other stuff .................


});

Ext.reg('x-mod-control-panelContenttask', AMD.Control.PanelContentTask);


the problem with this is that I no longer have the events to attach to as I want to play the audio file immediately in the callback. So does this mean I should just use the uxmedia to attempt to play the audio files? I realize this requires the flash plugin but at this point it might be the easiest thing to do.

If I don't do that, then I need to somehow instantiate the AudioEvents class inside those capability routines and play the correct file. I can have different versions, that's not a problem....but the problem is that I don't know how to pass the audioUrl to the AudioEvents class as I do not need to play the file upon an event instance, but rather I just need to play it NOW. The only way I see to pass the actual file to play is via an event listener in the config.

HELP PLEASE?!

Bucs
30 Jun 2010, 4:01 PM
Doug, just an FYI...that SoundManager2 JS library I mentioned in prior post is extremely robust and effective at doing everything I have mentioned here in terms of methods and event handling. Plays very nice with the extension lib and you can simply use component listeners to get all the event component event hooks. It is currently in the process of baking in HTML5 support as well. I had to go this route as opposed to using your extension due to the event handling capabilities.

In my opinion, you should consider wrapping this as you did the JWPlayer component. Flash is going to be around for a while (see YouTube comments) and it has wide browser compatibility as you know.

Whatever the case, your forum support is top notch along with the components you provide to the community :) So thanks for all that :)

hendricd
1 Jul 2010, 6:41 AM
@Bucs-- The anatomy of a Panel (and its load methods) is causing some confusion.

Since the body of a Panel is the target for loaded content, you would simply bind the AudioEvent plugin to its (body) Updater after you have configured a suitable fallback mediaCfg post-audio feature detection.

Remember, the plugin can be bound to anything that fires events.

See below:



AMD.Control.PanelContentTask = Ext.extend(Ext.Panel, {
/* ===================================================================================== */
// BEGIN: STATIC CONFIG PROPERTIES
id: 'pnlContentTask'
,title: 'Loading...'
,width: 610
,height: 355
,layout: 'form'
,frame: false
,iconCls: 'formColors'

// END : STATIC CONFIG PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM PROPERTIES
, contentUrl: ''
, wavUrl : 'media/mediaStream.wav'
, mp3Url : 'media/mediaStream.mp3'
// END : CUSTOM PROPERTIES
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: COMPONENT INIT

, initComponent: function() {

// Setup title and content
if(this.inTitle != '') this.title = this.inTitle;
if(this.inContentUrl != '') this.contentUrl = this.inContentUrl;

// Build toolbar
var tb = new Ext.Toolbar({
items: [
{
xtype: 'tbfill'
},
{
id : 'btnProceed',
xtype : 'button',
text : 'Start Next Task Now',
iconCls : 'next',
disabled: false,
handler : this.markTaskComplete
},
{
text : 'Stop',
handler : function(){
var updater = this.getUpdater();
updater.audioPlugin && updater.audioPlugin.stopAudio();

//or
//this.audioPlugin && this.audioPlugin.stop();
},
scope : this

}
]
});

// Setup button bar buttons
this.bbar = tb;

AMD.Control.PanelContentTask.superclass.initComponent.call(this);

this.on('afterrender', this.startup, this);

}

// END : COMPONENT INIT
/* ===================================================================================== */

/* ===================================================================================== */
// BEGIN: CUSTOM METHODS


, displayContent: function(contentUrl, audioUrl){

if(audioUrl){ //each page's audio file will likely be different, right?
this.audioPlugin.stop();
this.audioPlugin.audioEvents.update = audioUrl;
}

var pnlMgr = this.getUpdater();

// Perform Load
pnlMgr.update({
url: contentUrl || this.contentUrl, //load the next page?
indicatorText: 'Please wait...',
text: 'Please wait...',
timeout: 30,
scripts: true
});

}

,initAudio: function(){

var stream,
caps = Ext.capabilities,
mediaCfg;

if(caps && caps.hasAudio){ //HTML5 support ?
stream = caps.hasAudio.wav ? this.wavUrl :
( caps.hasAudio.mp3 ? this.mp3Url : null );
}
if(!stream){ //Fallback to a WAV player
mediaCfg = {
mediaType : 'WAV' //use the widest available WAV support (OR ANY other profile you wish to support)
start : false
};
stream = this.wavUrl;
}
this.audioPlugin = new Ext.ux.Media.plugin.AudioEvents({
mediaCfg : mediaCfg,
hideMode : 'offsets', //remove if you intend to render controls somewhere
controls : false, //true if you itend to render player controls somewhere
height : 60,
style : 'padding-top:12px',
audioEvents :{
update: stream, //the url the event will play
failure : 'media/oops.wav'
},
volume : .5
});

this.audioPlugin.init( this.getUpdater() ); //bind to Updater's update event

},

startup : function(){
this.initAudio();
this.displayContent(); //load the first page

}

//................ other stuff .................


});

Ext.reg('x-mod-control-panelContenttask', AMD.Control.PanelContentTask);
Tweak it. ;)

hendricd
4 May 2012, 6:15 AM
hendricd, do you have github account?




hendricd@