AIR-Ajax Video player

Immagini

Immagine 1 Immagine 2 Immagine 3 Immagine 4

di Matteo Ronchi

Adobe Air offre molteplici possibilità per realizzare le nostre applicazioni desktop, mentre la maggior parte dei tutorial disponibili sulla rete mostra come creare interfacce basate su Flex e Flash in questo articolo intendo dare risalto all’uso di codice Javascript per generare un semplice desktop video player. Questo tutorial mostra come creare la nostra applicazione usando Aptana Studio, un potente editor di programmazione basato su Eclipse creato per sviluppatori Ajax. Aptana Studio offre numerosi strumenti d’ausilio ai programmatori web che utilizzano tecnologie Ajax e di conseguenza è un candidato naturale come ambiente di sviluppo per creare applicazioni Adobe AIR basate su questo linguaggio.

L’editor offre inoltre un plugin nativo che permette allo sviluppatore di non doversi preoccupare del setup del compilatore distribuito con l’SDK ma di potersi concentrare unicamente sulla realizzazione della propria applicazione. Aptana Studio offre comandi built-in per eseguire in fase di test la nostra applicazione e per compilarne la versione ridistribuibile quando necessario. La generazione dell’eseguibile avviene tramite un comodo wizard che ci permette di configurare i dettagli richiesti dal compilatore.

Potete scaricare Aptana Studio da qui: http://www.aptana.com/studio, una volta installato, dalla StartPage visualizzata selezionate l’opzione per scaricare il plugin per creare applicazioni Adobe AIR.

A questo punto siete pronti a procedere.

Creiamo un progetto AIR in Aptana Studio
Apriamo Aptana Studio e creiamo un nuovo progetto Adobe AIR.
(Immagine 1)

Selezionato il tipo di progetto ci viene chiesto di definire nome e posizione sul disco del progetto.
(Immagine 2)

Eventualmente Aptana ci offre la possibilità di creare un progetto integrato con un server Ajax da loro offerto. Successivamente ci vengono offerte due schede per definire i dettagli che andranno a costruire il file XML descrittore usato dal compilatore di Adobe AIR per generare ed eseguire la nostra applicazione. Il primo dei due dialog definisce aspetti dell’applicazione quale id, nome e descrizione dell’eseguibile da generare ed eventualmente permette di impostare delle icone personalizzate. Quello successivo si occupa di dimensioni, posizione e aspetto della finestra della nostra applicazione.
(Immagine 3)

Infine possiamo definire fin da subito eventuali librerie Ajax che andremo ad usare in modo che il programma le importi per noi.
(Immagine 4)
Il file XML generato sarà simile a questo:

  1. <?xml version=”1.0” encoding=”UTF-8”?>
  2. <application xmlns=”http://ns.adobe.com/air/application/1.0”>
  3. <id>com.flexgala.app.simpleVideo</id>
  4. <filename>flexGalaSimpleVideo</filename>
  5. <name>FlexGala Ajax Video Player</name>
  6. <version>1.0</version>
  7. <description>FlexGala Video Player</description>
  8. <copyright>Flexgala.com</copyright>
  9. <initialWindow>
  10. <content>index.html</content>
  11. <title>FlexGala.com Simple Video Player</title>
  12. <systemChrome>standard</systemChrome>
  13. <transparent>false</transparent>
  14. <visible>false</visible>
  15. <minimizable>true</minimizable>
  16. <maximizable>true</maximizable>
  17. <resizable>true</resizable>
  18. <width>640</width>
  19. <height>400</height>
  20. <x>200</x>
  21. <y>200</y>
  22. <minSize>400 300</minSize>
  23. <maxSize>1640 1400</maxSize>
  24. </initialWindow>
  25. <icon>
  26. <image16x16>icons/icon_16.png</image16x16>
  27. <image32x32>icons/icon_32.png</image32x32>
  28. <image48x48>icons/icon_48.png</image48x48>
  29. <image128x128>icons/icon_128.png</image128x128>
  30. </icon>
  31. </application>

questo documento sarà successivamente modificabile se necessario, dovrete però aggiornarlo manualmente prima di ricompilare l’applicazione.

Creiamo il layout HTML principale
Ora andiamo a definire il contenuto del file principale della nostra applicazione (index.html). Questo documento funzionerà da main controller per la nostra applicazione, si occuperò quindi di definire le funzionalità tramite javascript ed il layout grafico usando degli Iframe. Adobe AIR estende il DOM tradizionale di un documento HTML aggiungendo ad alcuni elementi (tra cui gli Iframe) attributi e proprietà supplementari per rendere più agile lo sviluppo di applicazioni AIR Ajax.
All’interno del tag Head andiamo ad importare i file javascript che definiscono la business logic:

  1. <head>
  2. <title>FlexGala Video Player</title>
  3. <!-- javascript per interagire con API di Adobe Air -->
  4. <script type=”text/javascript” src=”lib/js/air/AIRAliases.js”></script>
  5. <!-- javascript per interagire con Adobe Air Introspector -->
  6. <script type=”text/javascript” src=”lib/js/air/AIRIntrospector.js”></script>
  7. <!-- foglio di stile per l’applicazione -->
  8. <link href=”lib/css/appStyle.css” rel=”stylesheet” type=”text/css” />
  9. <!-- business logic -->
  10. <script src=”lib/js/ErrorManagement.js” type=”text/javascript”></script>
  11. <script src=”lib/js/Utils.js” type=”text/javascript”></script>
  12. <script src=”lib/js/VideoSetup.js” type=”text/javascript”></script>
  13. <script src=”lib/js/main.js” type=”text/javascript”></script>
  14. </head>

All’interno del Body del documento HTML importiamo in un Iframe i controlli di riproduzione del nostro video e registramo una funzione ‘doLoad()’ al caricamento avvenuto del DOM. Utilizzando Iframe che importano documenti HTML esterni possiamo definire dei moduli riutilizzabili per le nostre applicazioni AIR.

  1. <body id=”mainWin” onLoad=”doLoad();”>
  2. <iframe
  3. id=”videoContainer”
  4. src=”video.html”/>
  5. </body>

Definiamo controlli di riproduzione usando un Iframe il documento HTML caricato nell’IFrame definisce i controlli di riproduzione, la barra di riferimento temporale ed il pulsante per richiedere la finestra di selezione del file video:

  1. <html>
  2. <head>
  3. <title>Video Frame</title>
  4. <!-- foglio di stile per i controlli -->
  5. <link href=”lib/css/video.css” type=”text/css” rel=”stylesheet” />
  6. <!-- Usiamo la libreria Prototype per calcolare le dimensioni del layout -->
  7. <script src=”lib/js/prototype/prototype-1_5_1_1.js” type=”text/javascript”></script>
  8. <!-- JavaScript business logic -->
  9. <script src=”lib/js/iFrame.js” type=”text/javascript”></script>
  10. </head>
  11. <body onLoad=”doLoad();”>
  12. <!-- Control bar at the bottom of the screen -->
  13. <!-- I controlli di riproduzione vengono posti nella parte inferiore dell’applicazione -->
  14. <div id=”controls”>
  15. <img id=”play” src=”assets/play-up.gif” width=”46” height=”23” />
  16. <div id=”progress”></div>
  17. <img id=”head” src=”assets/playhead.gif” width=”7” height=”5” />
  18. <img id=”open” src=”assets/open-up.gif” width=”23” height=”23” />
  19. </div>
  20. </body>
  21. </html>

Questo documento HTML usa la libreria Ajax ‘prototype’ per calcolare la dimensione della barra di caricamento e poter così definire correttamente la posizione del cursore di riproduzione. Il codice Javascript associato si occupa di definire l’interazione con i pulsanti ed il loro feedback grafico. Si occupa inoltre di aggiornare quando richiesto dall’applicazione principale la testina di riproduzione. La funzione ‘doLoad()’ chiamata a caricamento del DOM avvenuto è la seguente:

  1. // Chiamata quando il DOM dell’Iframe マ caricato
  2. // configura controlli di riproduzione e sandbox di comunicazione
  3. function doLoad()
  4. {
  5. var exposed = new Object();
  6. // associamo le funzioni tra main HTML e IFrame
  7. // senza violare restrizioni di sicurezza
  8. // usando la proprietˆ ‘childSandboxBridge’
  9. // aggiunta da Adobe AIR agli Iframe
  10. exposed.resetPlayhead = resetPlayhead;
  11. exposed.setPlayhead = setPlayhead;
  12. childSandboxBridge = exposed;
  13. // configuriamo effetti interazione controlli di riproduzione
  14. document.getElementById( ‘play’ ).addEventListener( ‘mouseover’, doPlayOver );
  15. document.getElementById( ‘play’ ).addEventListener( ‘mouseout’, doPlayOut );
  16. document.getElementById( ‘play’ ).addEventListener( ‘mousedown’, doPlayDown );
  17. document.getElementById( ‘play’ ).addEventListener( ‘mouseup’, doPlayUp );
  18. document.getElementById( ‘play’ ).addEventListener( ‘click’, doPlayClick );
  19. document.getElementById( ‘open’ ).addEventListener( ‘mouseover’, doOpenOver );
  20. document.getElementById( ‘open’ ).addEventListener( ‘mouseout’, doOpenOut );
  21. document.getElementById( ‘open’ ).addEventListener( ‘mousedown’, doOpenDown );
  22. document.getElementById( ‘open’ ).addEventListener( ‘mouseup’, doOpenUp );
  23. document.getElementById( ‘open’ ).addEventListener( ‘click’, doOpenClick );
  24. // azzeriamo posizione testina di riproduzione
  25. resetPlayhead();
  26. }

Per avere una visione completa del documento javascript e dell’implementazione delle funzionalità nel dettaglio fate riferimento all’evento completo allegato all’articolo.

Aggiungiamo codice Javascript per caricare il video
Nella funzione chiamata ad inizializzazione del DOM del documento HTML pricipale avvenuta ci occupiamo di istanziare e mettere nella disply list della nostra applicazione un controllo video esposto dalle API di Adobe AIR all’ambiente Javascript, andiamo anche a definire una mappatura tra funzioni definite dall’applicazione principale e delle proprietà accessibili ai controlli all’interno dell’IFrame, in questo modo potemo associare, all’interno del modulo importato, degli eventi d’interazione con le funzioni esposte.

  1. // Chiamata quando il video è stato caricato dal filesystem
  2. // configura controlli di riproduzione e sandbox di comunicazione
  3. function doInitVideo()
  4. {
  5. var exposed = new Object();
  6. // associamo le funzioni tra main HTML e IFrame
  7. // senza violare restrizioni di sicurezza
  8. // usando la proprietà ‘parentSandboxBridge’
  9. // aggiunta da Adobe AIR agli Iframe
  10. exposed.open = open;
  11. exposed.pause = pause;
  12. exposed.resume = resume;
  13. document.getElementById( ‘videoContainer’ ).contentWindow.parentSandboxBridge = exposed;
  14. // definiamo la cartella in cui si aprirà
  15. // il dialog di selezione del video
  16. flv = air.File.desktopDirectory;
  17. flv.addEventListener( air.Event.SELECT, doSelect );
  18. // associamo all’evento di ENTER_FRAME la funzione
  19. // che controlla la testina di riproduzione del video
  20. window.htmlLoader.stage.addEventListener( air.Event.ENTER_FRAME, doFrame );
  21. // Inizializziamo la connessione per il video
  22. // senza specificare nessun serer di streaming,
  23. // in quanto non ne usiamo
  24. conn = new air.NetConnection();
  25. conn.connect( null );
  26. // Inizializzaimo un flusso video e
  27. // lo associamo alla connessione aperta
  28. // monitoriamo gli eventi di stato e metadati correlati al flusso
  29. stream = new runtime.flash.net.NetStream( conn );
  30. stream.client = this;
  31. stream.addEventListener( air.NetStatusEvent.NET_STATUS, doStatus );
  32. // Inizializziamo un oggetto video di Flash
  33. // Attacchiamo il video al flusso video
  34. video = new air.Video();
  35. video.attachNetStream( stream );
  36. // poniamo il video sopra il cotrollo HTML
  37. // che contiene la nostra applicazione
  38. window.htmlLoader.stage.addChild( video );
  39. // Centriamo l’applicazione nello schermo
  40. center();
  41. }

Il controllo HTML che contiene la nostra applicazione Ajax non permette di aggiungere al suo interno istanze di oggetti creati tramite le API di Adobe AIR, come il video display per esempio, quindi dobbiamo andare a posizionare il controllo sovrapposto al di sopra del layer HTML. Questo è possibile perchè le applicazioni Adobe AIR programmate in Ajax vengono compilate ed incorporate in un’istanza Actionscript che offre funzionalità di un Display Object Container e ci permette dunque di usare delle API standard per aggiungere oggetti in overlay allo strato HTML. Definendo l’istanza dell’oggetto video abbiamo registrato una funzione alla ricezione dei metadata del video in caricamento. In questa funzione ci preoccuperemo di leggere durata e dimensioni del video e di deguare l’aspetto del nostro video player:

  1. // chiamata quando i Metadati inerenti il video sono disponibili
  2. // NB. Se il video non definisce informazioni metadata non potremo
  3. // ridimensionare la finestra correttamente
  4. function onMetaData( e )
  5. {
  6. // durata totale del video
  7. totalTime = Math.floor( e.duration );
  8. // scriviamo la durata del video nella console di debug
  9. air.Introspector.Console.log( “video duration: “ + totalTime );
  10. // verifichiamo se sono disponibili informazioni di dimensione
  11. if( e.width != null )
  12. {
  13. // Ridimensioniamo display video
  14. video.width = e.width;
  15. video.height = e.height;
  16. // ridimensioniamo finestra
  17. fit( e.width, e.height );
  18. // Centriamo l’applicazione nello schermo
  19. center();
  20. }
  21. }

Quando ridimensioniamo la finestra adeguandola alle nuove dimensioni del video dobbiamo tenere conto anche degli ingombri dati dalla barra del titolo e dai bordi della finestra più, ovviamente, l’ingombro dei controlli di riproduzione.

  1. // Ridimensiona la finestra dell’applicazione a dimensione del video caricato
  2. // viene tenuto conto anche delle dimensioni occupate dalla barra del titolo
  3. // ed i vordi della finestra
  4. function fit( width, height )
  5. {
  6. // Calcoliamo ingombro elemnti della finestra nativa
  7. var chromeHeight = window.nativeWindow.height - window.htmlLoader.stage.stageHeight;
  8. var chromeWidth = window.nativeWindow.width - window.htmlLoader.stage.stageWidth;
  9. // Ridimensioniamo la finestra per contenere correttamente
  10. // il video caricato
  11. window.nativeWindow.width = chromeWidth + width;
  12. window.nativeWindow.height = chromeHeight + CONTROL_HEIGHT + height;
  13. // posizioniamo la finestra video se necessario
  14. if( video.width < MIN_WIDTH ) {
  15. video.x = ( MIN_WIDTH - video.width ) / 2;
  16. }else{
  17. video.x = 0;
  18. } if( video.height <
  19. (
  20. MIN_HEIGHT -
  21. chromeHeight -
  22. CONTROL_HEIGHT )
  23. )
  24. {
  25. video.y = ( ( MIN_HEIGHT - chromeHeight - CONTROL_HEIGHT ) - video.height ) / 2;
  26. }else{
  27. video.y = 0;
  28. }
  29. // scriviamo nella console l’altezza attuale della finestra
  30. air.Introspector.Console.log( “nativeWindow.height: “ + nativeWindow.height );
  31. }

Per sincronizzare il cursore della testina di riproduzione al flusso video abbiamo registrato la funzione ‘doFrame()’ all’evento di EnterFrame dell’applicazione, così ad ogni aggiornamento del display ci preoccuperemo di aggiornare anche la posizione della testina:

  1. // Chiamata ad ogni evento di ENTER_FRAME dell’applicazione
  2. // si occupa di aggiornare la testina di riproduzione del video
  3. function doFrame( e )
  4. {
  5. var current = null;
  6. // verifichiamo se i lvideo マ in riproduzione
  7. if( isPlaying )
  8. {
  9. // Dcalcoliamo percentuale di video riprodotta
  10. current = stream.time / totalTime;
  11. // posizioniamo il cursore
  12. document.getElementById( ‘videoContainer’ ).
  13. contentWindow.childSandboxBridge.setPlayhead( current );
  14. }
  15. }

AIRIntrospector, il debugger per applicazioni Ajax-AIR
In alcune delle funzioni sopra riportate avrete notato delle istruzioni che si riferivano alla classe ‘air.Introspector.Console’, questa è responsabile di interagire con il debugger offerto da Adobe per applicazioni AIR sviluppate con tecnologia Ajax. AIRIntrospector è una replica fedele del noto plugin per Mozilla Firefox: FireBug, come FireBug si può mostrare o nascondere usando il tasto F12 oppure lo si può far apprire richiedendo un log nella console di output.

Per poter accedere ad AIRIntrospector bisogna accertrsi di avere importato il file javascript ‘AIRIntrospector.js’ nel documento HTML. Ora sta a voi affrontare la sfida di creare applicazioni Adobe AIR usando HTML ed Ajax, il limite è solo la vostra creatività.

________________________________________________________________

Matteo Ronchi
m.ronchi@cef62.com
Dopo un passato da montatore video e modellatore 3D, ha iniziato a conoscere il mondo dei contenuti multimediali e ad appassionarsene grazie a Macromedia Director. Da qui il passo verso la programmazione e la creazione di contenuti interattivi e applicazioni Actionscript, Flex e Adobe Air è stato breve. Oggi sperimenta soluzioni creative che si avvalgono delle possibilità offerte da librerie quali papervision3D e Sandy.