Avatar billede edinger Nybegynder
21. april 2008 - 23:09 Der er 9 kommentarer

Flash / XML mp3 afspiller - hjælp til ny funktion søges!!

Hej!

Jeg har fulgt en tutorial af Lee Brimelow på gotoandlearn.com hvor man bygger en Flash/XML mp3 afspiller.
Men jeg har brug for en ekstra funktion - muligheden for at vælge tracks direkte udover bare at trykke på "next"-knappen.

Er der nogen der hjælpe til at target'e en hvilken som helst sang fra XML'en direkte fra en tilegnet knap? Og bagefter lade afspilleren springe videre til den næste sang efter den valgte på XML-listen når den den valgte sang er forbi?

Den side hvorfra jeg skal kalde sangene skal have layout som en diskografi. Flere CD-covers med to-tre sange tilknyttet. En "play"-knap ud for hver sang. Klik på en hvilkensomhelst sang og den afspilles i playeren og går automatisk videre til den næste sang i XML-listen.
Men stadig med mulighed for at vælge en anden sang direkte.

Jeg ville foretrække at kunne target'e hver sang med et unikt ID som fx URL eller tracknavn fremfor bare hvilket nummer den er i XML'en.

Nedenfor kan I se mine forsøg so far:

Jeg har tilføjet denne sektion til Lee's kode)

<em>// Play the MP3 File #3 (mit eget forsøg på kode til at kalde sang nr 3))</em>

og denne bid kode til knappen:

<em>// Song3 Button</em>

[code]// Setup sound object
var s:Sound = new Sound();
s.onSoundComplete = playSong;
s.setVolume(75);

// Array of songs
var sa:Array = new Array();

// Currently playing song
var cps:Number = -1;

// Position of music
var pos:Number;

// Load the songs XML
var xml:XML = new XML();
xml.ignoreWhite = true;
xml.onLoad = function()
{
    var nodes:Array = this.firstChild.childNodes;
    for(var i=0;i<nodes.length;i++)
    {
        sa.push(new Song(nodes[i].attributes.url, nodes[i].attributes.track, nodes[i].attributes.artist));
    }
    playSong();
}

xml.load("songs.xml");

// Play the MP3 File
function playSong():Void
{
    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    mute.gotoAndStop("on");
    if(cps == sa.length - 1)
    {
        cps = 0;
        s.loadSound(sa[cps].earl, true);
    }
    else
    {
        s.loadSound(sa[++cps].earl, true);
    }
    trackInfo.text = sa[cps].track + " - " + sa[cps].artist;
    playPause.gotoAndStop("pause");
    textPos = 0;
}

// Play the MP3 File #3 (Mit eget forsøg)
function playSong3():Void
{
    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    s.loadSound(sa[2].earl, true);
    trackInfo.text = sa[2].track;
    playPause.gotoAndStop("pause");
    textPos = 0;
}

// Pauses the music
function pauseIt():Void
{
    pos = s.position;
    s.stop();
}

// Pauses the music
function unPauseIt():Void
{
    s.start(pos/1000);
}

// Music Controls

// Play/Pause Toggle
playPause.onRollOver = function()
{
    if(this._currentframe == 1) this.gotoAndStop("pauseOver");
    else this.gotoAndStop("playOver");
}

playPause.onRollOut = playPause.onReleaseOutside = function()
{
    if(this._currentframe == 10) this.gotoAndStop("pause");
    else this.gotoAndStop("play");
}

playPause.onRelease = function()
{
    if(this._currentframe == 10)
    {
        this.gotoAndStop("playOver");
        this._parent.pauseIt();
    }
    else
    {
        this.gotoAndStop("pauseOver");
        this._parent.unPauseIt();
        holder.playPause.gotoAndStop("play");
        holder.audioStop();
    }
}

// Next Button
next.onRollOver = function()
{
    this.gotoAndStop("nextOver");
}

next.onRollOut = next.onReleaseOutside = function()
{
    this.gotoAndStop("next");
}

next.onRelease = function()
{
    this._parent.playSong();
}

// Song3 Button
song3.onRollOver = function()
{
    this.gotoAndStop("song3Over");
}

song3.onRollOut = song3.onReleaseOutside = function()
{
    this.gotoAndStop("song3");
}

song3.onRelease = function()
{
    this._parent.playSong3();
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Text scroller bonus codes

var size:Number = 50;
var textPos:Number = 0;
var intervalID:Number = setInterval(scroller, 1000);

function scroller():Void
{
    var t:String = (sa[cps].track);
    if(textPos+size < t.length)
    {
        textPos++;
        trackInfo.text = (sa[cps].track).substring(textPos, textPos+size);
    }
    else
    {
        clearInterval(intervalID);
        intervalID = setInterval(scroller2, 1000);
    }
}

function scroller2():Void
{
    var t:String = (sa[cps].track);
    if(textPos > 0)
    {
        textPos--;
        trackInfo.text = (sa[cps].track).substring(textPos, size);
    }
    else
    {
        clearInterval(intervalID);
        intervalID = setInterval(scroller, 1000);
    }
}
[/code]

Min XML-fil:
[code]<?xml version="1.0" encoding="UTF-8"?>
<songs>
    <song url="songs/02secretsfrometernity.mp3" track="SECRETS FROM ETERNITY" artist="CLAUS WAIDTLØW GROUP" />
    <song url="songs/03waltzforalbert.mp3" track="WALTZ FOR ALBERT" artist="CLAUS WAIDTLØW GROUP" />
    <song url="songs/01ghostville.mp3" track="GHOSTVILLE" artist="CLAUS WAIDTLØW GROUP" />
</songs>[/code]

Og min song.as-fil:
[code]class Song
{
    public var earl:String;
    public var track:String;
    public var artist:String;
   
    public function Song(e:String, t:String, a:String)
    {
        earl = e;
        track = t;
        artist = a;
    }
}[/code]

Det er lykkedes mig at få song3-knappen til at virke halvt. Ved klik hopper playeren til den tredie entry på XML-listen.
Men derefter har nextknappen ikke den ønskede funktion:
eksempel 1:
Sang1 afspilles.
song3-knappen trykkes ned og sang3 afspilles.
Next-knappen trykkes ned og song2 afspilles.

eksempel 2:
Sang2 afspilles.
Song3-knappen trykkes ned og sang3 afspilles.
Next-Knappen trykkes ned og nu starter sang 3 forfra.

Er der nogen der kan hjælpe mig?
Jeg er bestemt ikke nogen erfaren coder. Løsningen med at kalde et nummer fra XML-listen var det bedste jeg kunne finde på men, jeg ville hellere kunne target'e en unik identifier. Og selvfølgelig kunne få den forventede opførsel når man trykker "next".

En anden ting:

Jeg kan ikke få flash til at vise den "string value" (" - ") som skal stå imellem "track" og "artist". Den viser bare et mellemrum. Mærkeligt.

Al hjælp modtages med kyshånd!

Tak!

Thomas.
Avatar billede thesurfer Nybegynder
21. april 2008 - 23:39 #1
Du skal huske at sætte cps til at være lig sang-nummeret..

Eksempel:

Afspil sang index 2 (dvs, 3. sang):
...din kode...
cps = 2;
... din kode

Eksempel:

function playSong3():Void
{
    cps = 2;

    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    s.loadSound(sa[cps].earl, true);
    trackInfo.text = sa[cps].track;
    playPause.gotoAndStop("pause");
    textPos = 0;
}
Avatar billede thesurfer Nybegynder
21. april 2008 - 23:42 #2
Mht " - ":

Der står hvordan du gør, i den originale playSong funktion:

    trackInfo.text = sa[cps].track + " - " + sa[cps].artist;

Hvis du samtidigt bruger "cps = 2;" fra mit første indlæg, bør du overhovedet ikke have problemer..
Avatar billede edinger Nybegynder
22. april 2008 - 09:04 #3
@ thesurfer:

Tusind tak for svaret.

Det virker perfekt! Mht til

"trackInfo.text = sa[cps].track + " - " + sa[cps].artist;"

så havde jeg overset at jeg ikke havde fået rettet den i playSong3-funktionen. TAK!

Imidlertid fik jeg aldrig bindestregen frem i hverken den ene eller anden funktion, men jeg har lige fundet ud af at det simpelthen var fordi at jeg havde glemt at embed'e bindestregen... flot ikke? :-)

Men var det en mulighed at kalde sangen med en unik identifier?

Jeg tænker at kalde fx URL på sangen eller tilføje en ny attribut til hver node i XML som er en et unikt ID? Hvis man nu i fremtiden havde brug for at tilføje flere sange til XML'en og herved måske ændre i rækkefølgen...
Så kunne man måske slippe for at ændre i koden til alle knapperne til sangene, men stadig have at resultatet var at afspilleren gik til næste sang på xml-listen ved tryk på nextknappen. Jeg håber min formulering er til at forstå. På forhånd tak!
Avatar billede thesurfer Nybegynder
22. april 2008 - 21:58 #4
Jeg er ikke Flash-programmør, men Action Script ligner med JavaScript, og jeg kan derfor programmere lidt AS..

Så vidt jeg kan se, skal din play-funktion se sådan ud:

function playSong3(cps:Number):Void

Så behøver du ikke linien:

    cps = 2;

Funktionen kaldes i stedet med:

playSong3(2);

eller

DitMovieClip.playSong3(2);

Så skulle den loaded 3. sang, da 2 jo er trede index..
Avatar billede thesurfer Nybegynder
22. april 2008 - 22:01 #5
Rettelse: "Action Script ligner meget JavaScript"

Husk at checke om værdien i cps (det medsendte) er større en længden af arrayen.. hvis den er det, skal den sættes til 0, inden du prøver på at tilgå sangen..
Og omvendt, skal du checke om værdien er under 0.. hvis den er det, skal du sætte den til det sidste index i arrayen..
Avatar billede edinger Nybegynder
24. april 2008 - 08:23 #6
@the surfer.

Tusind tak for hjælpen!

Det virker - næsten for mig!

Her er min kode:

// Play specific Mp3 file (number in xml list -1)
function playSongNumber(cps:Number):Void
{
    this._parent.playPause.gotoAndStop("play");
    this._parent.pauseIt();
    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    s.loadSound(sa[cps].earl, true);
    trackInfo.text = sa[cps].track + " - " + sa[cps].artist;
    playPause.gotoAndStop("pause");
    textPos = 0;
}

Og koden til et par knapper:
//Play song #1
play1.onRelease = function()
{
    this._parent.playSongNumber(0);
}

//Play song #5
play5.onRelease = function()
{
    this._parent.playSongNumber(4);
}

Det fungerer for så vidt idet et tryk på knappen kalder den rigtige sang. Men når sangen slutter, eller jeg trykker på next-knappen, går sangen ikke videre til næste sang efter den valgte i XML-listen.

Eksempel.

jeg åbner dokumentet og trykker gentagne gange på next indtil sang nr 7 afspilles.
Mens sang nr 7 afspilles trykker jeg på "play5" og sang nr 5 begynder.
trykker jeg derefter på next (eller venter til sangen er ovre) starter sang nr 8.

Her skulle det jo helst være sang nr 6...

Jeg tænker at det nok har noget at gøre med din sidste post:
Husk at checke om værdien i cps (det medsendte) er større en længden af arrayen.. hvis den er det, skal den sættes til 0, inden du prøver på at tilgå sangen..
Og omvendt, skal du checke om værdien er under 0.. hvis den er det, skal du sætte den til det sidste index i arrayen..

Jeg forstod bare ikke rigtig det afsnit... er ikke så stiv i arrays.

Kan du hjælpe mig lidt videre?

Tusind tak!

mvh Thomas
Avatar billede thesurfer Nybegynder
24. april 2008 - 23:10 #7
Jeg tror at det er fordi den globale variabel "cps" ikke ændres, men tages direkte i brug..

Hvis det er tilfældigt, burde dette løse problemet:

// Play specific Mp3 file (number in xml list -1)
function playSongNumber(nytindex:Number):Void
{
    cps = nytindex;
    this._parent.playPause.gotoAndStop("play");
    this._parent.pauseIt();
    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    s.loadSound(sa[cps].earl, true);
    trackInfo.text = sa[cps].track + " - " + sa[cps].artist;
    playPause.gotoAndStop("pause");
    textPos = 0;
}

Som du kan se, har jeg ændret "cps" til "nytindex" i funktionen:

function playSongNumber(nytindex:Number):Void

Jeg ændrer også værdien af den globale variabel "cps":

    cps = nytindex;

Så burde det virke..


Man burde også kunne bruge noget i stil med:

function playSongNumber(cps:Number):Void
{
    this.cps = cps;

...osv..

Dette gælder hvis man kan tilgå globale variabler (på klasse-niveau) ved at bruge "this.variabelnavn"..


Men prøv lige følgende:

// Play specific Mp3 file (number in xml list -1)
function playSongNumber(nytindex:Number):Void
{
    cps = nytindex;
    this._parent.playPause.gotoAndStop("play");
    this._parent.pauseIt();
    s = new Sound();
    s.onSoundComplete = playSong;
    s.setVolume(75);
    s.loadSound(sa[cps].earl, true);
    trackInfo.text = sa[cps].track + " - " + sa[cps].artist;
    playPause.gotoAndStop("pause");
    textPos = 0;
}
Avatar billede thesurfer Nybegynder
24. april 2008 - 23:52 #8
Mht det med arrayen, indlæg 22/04-2008 22:01:16:

Imodsætning til et menneske, tager en computer koden alvorligt og bogstaveligt :-)

Arrays starter ved index/position/plads 0 (også kaldet zero-based). Næste index er 1, derefter 2 osv..
Arrays har en eller anden længde, og det sidste index i array har nummeret "arrayens længde minus 1 da arrayen er zero-based".

Eksempel:
Du har 3 frugter i en array
index 0: æble
index 1: pære
index 2: banan

Det sidste index er 3 (antallet af frugter i arrayen) minus 1 (da arrayen er zero-based) er lig 2.

Et andet eksempel, der demonstrerer hvorfor man skal checke 0/arrayens længde:

Lad os sige, at du har 5 blyanter, med disse farver:

rød, grøn, blå, gul, lilla

Hver gang jeg siger "næste" til dig, skal du sige mig navnet på den næste blyant..
Da arrays er zero-based, står du allerede ved "rød", og vil sige "grøn" når jeg siger "næste"

Simulation:

theSurfer: næste
edinger: grøn

theSurfer: næste
edinger: blå

theSurfer: næste
edinger: gul

theSurfer: næste
edinger: lilla

theSurfer: næste
edinger: ????????????????????

Det skal lige siges at "????????????????????" betyder "mit system er gået ned fordi der ikke er nogen blyant på det index!"

Mennesker ville dog bare sige "der er ikke flere blyanter".. men fordi computere tager tingene bogstaveligt, vil den prøve på at sige farven på den ikke-eksisterende blyant, hvilket resulterer i et crash..

Det samme ville ske, hvis du stod på "rød" og jeg sagde "forrig", da der ikke er blyanter foran "rød".


Løsningen er:

theSurfer: Hvis du er står på index 0 ("rød") og jeg siger forrig, skal du hoppe til index arrayens-længde-minus-én (hvilket er "lilla"). Hvis du står på index arrayens-længde-minus-én ("lilla") og jeg siger "næste", skal du hoppe til første index (hvilket er "rød"). Med andre ord: kør i ring.


Koden kan se sådan ud, hvis man kun kan vælge "næste"

if (cps == sa.length - 1) cps = -1; // sæt index til at være før det første index, da næste linie lægger 1 til
cps++; // læg 1 til.. dvs: hvis cps er lig -1, bliver cps lig 0 (første index)
// Her gøres et eller andet med cps

Hvis man kan vælge både "næste" og "forrige", kan koden se sådan ud:

if (cps > sa.length - 1)
{
    // hvis der f.eks. kun er 5 blyanter (= index 4), og man spørger til 6. blyant (som skulle ligge på den manglende index 5)
    // start fra index 0 igen:
    cps = 0;
} else if ( cps < 0 ) {
    // man har valgt "blyanten" der ligge før "rød", hvilket jo ikke eksisterer,
    // så man tager fat i den sidste blyant:
    cps = sa.length - 1;
}
// Her gøres et eller andet med cps

Det kan godt være at det hedder "elseif" i stedet for "else if".. og hvis hverken kan bruge "elseif" eller "else if", kan man gøre sådan her:

if (cps > sa.length - 1)
{
    // hvis der f.eks. kun er 5 blyanter (= index 4), og man spørger til 6. blyant (som skulle ligge på den manglende index 5)
    // start fra index 0 igen:
    cps = 0;
} else {
    // man har valgt "blyanten" der ligge før "rød", hvilket jo ikke eksisterer,
    // så man tager fat i den sidste blyant:
    if ( cps < 0 ) cps = sa.length - 1;
}
// Her gøres et eller andet med cps


Jeg håber at det hjalp.. ellers må du lige sige til..
Avatar billede edinger Nybegynder
30. april 2008 - 23:30 #9
@surfer!

Tusind tak for din hjælp! Jeg er lige blevet skatteregnskabsramt, så jeg har ikke haft tid til at prøve din kode af... Men jeg er virkelig glad for din hjælp og ser frem til at prøve koden af snarest...

mvh Thomas
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester