[gelöst] Anzeige Totaltime für Liste von Audiodateien

Alles rund um die Programmierung mit Qt
Antworten
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

[gelöst] Anzeige Totaltime für Liste von Audiodateien

Beitrag von thebigear »

Hallo,

ich habe eine Liste von Audiodateien, (Nutzereingabe über getOpenFileNames). Nun möchte ich dem Nutzer gerne eine Übersicht präsentieren, in der neben jedem Dateinamen die Länge der Audiodatei angezeigt wird. Hierbei habe ich nun aber das Problem, dass ich hierzu auf ein MediaObject zugreifen muss:

Code: Alles auswählen

MediaObject.TotalTime()
Jedoch ist diese Information erst verfügbar, wenn das Media Object den LoadingState erreicht. Hierzu wird dann ein Signal ausgegeben:

Code: Alles auswählen

void MediaObject::totalTimeChanged ( qint64 newTotalTime )
Jetzt nun meine Frage, wie kann ich diese Information (TotalTime) für eine Liste (Dateinamen Audiofiles) beliebiger Länge herausbekommen, wenn mir jedes Mediaobject nur ein Signal gibt. Ich beim Slot für das Signal gar nicht weiß, welche von welchem MediaObject die info kommt.

Oder gibt es einen anderen Weg?

Danke Ingo
Zuletzt geändert von thebigear am 14. Oktober 2010 09:54, insgesamt 2-mal geändert.
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

QSignalMapper
sender()

Es wäre aber vermutlich Sinnvoller eine Metadaten-Reader zu basteln der die Headerinfos der Sounddateien auswertet ... das wo drin steht: Titel, Länge, Album, Tracks, ...

sonst musst du erst alle Sachen in den Speicher verfrachten (laden) bevor du Auskunft erhältst.
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

Beitrag von thebigear »

Vielen Dank für die schnelle Antwort.

Die Idee mit dem QSignalMapper klingt nicht schlecht, aber ich habe nun noch das Problem, wie ich aus den jetz aufgerufenen Slot die totalTime herausbekomme:

Hier mal meine Codeschnipsel:

Code: Alles auswählen

signalMapper = new QSignalMapper(this);

        for (int i = 0; i < AudiofileNameList.size(); ++i) {
            metaInformationResolver = new Phonon::MediaObject(this);
            metaInformationResolver->setCurrentSource(Phonon::MediaSource(AudiofileNameList.at(i)));
            connect(metaInformationResolver, SIGNAL(totalTimeChanged(qint64)), signalMapper, SLOT(map()));
            signalMapper->setMapping(metaInformationResolver,i);
        }

        connect( signalMapper, SIGNAL( mapped(int) ), this, SLOT( slotGetFileTime(int) ) );

Code: Alles auswählen

void kannotate::slotGetFileTime(int i){
    qDebug() << "ready file" <<i;
    // totalTime???
}
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Es reicht ein schneller Blick in "examples/phonon/qmusicplayer". Enteschiedend ist hier der "metaInformationResolver" im MainWindow. Schau dir im Konstruktor den connect mit dem metaInformationResolver an, und den SLOT "metaStateChanged". Dort kannst du dir die aktuelle Zeit mit dem metaInformationResolver->totalTime() ziehen und in die Table einfügen (in setupUi musst du noch eine zusätzliche Spalte einfügen). Funktioniert fabulös :P
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

Beitrag von thebigear »

Hallo franzf,

danke für die Info, aber das nützt mir glaub ich nichts, da ich ja n Audiodateien habe und ich, wenn das Signal kommt, nicht weiß, welche Datei dazugehört.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

thebigear hat geschrieben:da ich ja n Audiodateien habe und ich, wenn das Signal kommt, nicht weiß, welche Datei dazugehört.
metaInformationResolver->currentSource().fileName() wäre der Dateiname, bezogen auf das QMusicPlayer-Example. Probiers doch einfach mal aus, hier geht es, dann wirds bei dir auch gehen.
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

Beitrag von thebigear »

Hallo,

irgendwie krieg ich das nicht hin, stehe bestimmt auf dem schlauch:

Hier meine Code-Schnipsel (orientiere mich am Musicplayerbeispiel:
main:

Code: Alles auswählen

MainWindow::MainWindow(){
...
 metaInformationResolver = new Phonon::MediaObject(this);
    connect(metaInformationResolver, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
                 this, SLOT(metaStateChanged(PPhonon::State,Phonon::State)));
...}


Code: Alles auswählen

void MainWindow::slotOpenMultiAudio(){
do{
        AudiofileNameList = QFileDialog::getOpenFileNames(this, tr("Open Audio File"),XmlFilePath,tr("Audio Files (*.wav *.mp3)"));
        }while(AudiofileNameList.isEmpty());

        QMessageBox::information(this,tr("Loading successful"),tr("Have loaded %1 audiofiles.").arg(AudiofileNameList.size()));

        int index = sources.size();
        foreach (QString string, AudiofileNameList) {
            Phonon::MediaSource source(string);
            sources.append(source);
        }
        if (!sources.isEmpty()){
            metaInformationResolver->setCurrentSource(sources.at(index));
        }
}

Code: Alles auswählen

void kannotate::metaStateChanged(Phonon::State newState, Phonon::State oldState){
    qDebug() << "bin hier";
    qDebug() << metaInformationResolver->totalTime();
    Phonon::MediaSource source = metaInformationResolver->currentSource();
    int index = sources.indexOf(metaInformationResolver->currentSource()) + 1;
    ///index ist die nummer der Datei und totaltime ist die Länge !!! juhuu, ich habs
    if(sources.size() < index){
        metaInformationResolver->setCurrentSource(sources.at(index));
    }

}
Das Problem ist jetzt, dass er nur einmal in den slot metaStateChanged() geht und mir nur die Länge der ersten Datei liefert und nicht von allen!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

thebigear hat geschrieben:Das Problem ist jetzt, dass er nur einmal in den slot metaStateChanged() geht und mir nur die Länge der ersten Datei liefert und nicht von allen!
Wer lesen kann ist klar im Vorteil :P
">" != "<"! Schau in den metaStateChanged-SLOT, du weißt dann was ich meine.
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

Mal schaun :

Code: Alles auswählen

void MainWindow::slotOpenMultiAudio(){
do{
        AudiofileNameList = QFileDialog::getOpenFileNames(this, tr("Open Audio File"),XmlFilePath,tr("Audio Files (*.wav *.mp3)"));
        }while(AudiofileNameList.isEmpty());
Das Blockiert solange bis der was auswählt ... was wenn er dann doch nix auswählen möchte weil er nen Termin hat und weg muss? Wei wäre es statt do { } while() mit if (AudioDFileNameList.isEmpty()) return;

Code: Alles auswählen

        QMessageBox::information(this,tr("Loading successful"),tr("Have loaded %1 audiofiles.").arg(AudiofileNameList.size()));
Irreführend ... die sind noch nicht geladen. Besser: "Selected %1 files" ... oder einfach keine Messagebox(ich denke mal das ist nur zum debuggen .. dann iss egal?)

Code: Alles auswählen

        int index = sources.size();
        foreach (QString string, AudiofileNameList) {
            Phonon::MediaSource source(string);
            sources.append(source);
Wer bittesehr nennt eine Zeichenkette "string" ?!?! nenn das fileName oder file oder sonstwas, aber vermeide Namen die durch Klassen vorbelegt sind. Wenn du später mal using namspace std; oben reinpackst kriegste Ärger.

Davon mal abgesehen ... was glaubst du was passiert mit jeder einzelnen "source" wenn du die {} verlässt? Stichwort: SCOPE, HEAP, STACK.

Versuch mal

Code: Alles auswählen

Phonon::MediaSource * newSource = new Phonon::MediaSource(filename);
neuerMember_QListOfMediaSourceS.append(newSource);
und pack was in den Destruktor der das wieder aufräumt ...

Code: Alles auswählen

qDeleteAll(neuerMember_QListOfMedaSourceS);  neuerMember_QListOfMedaSourceS.clear();

Code: Alles auswählen

        }
        if (!sources.isEmpty()){
            metaInformationResolver->setCurrentSource(sources.at(index));
        }
}
Damit setzt du das ganze auf die !!vorherige!! größe der sources ... also auf was was vor dem Slot schon drin war ... war nix drin gibts kein ärger (da empty, if verhindert das), war was drin gibts noch keinen Ärger, würde aber sobald du versuchst auf etwas zuzugreifen das bei index+x in sources liegt (x in (1..AnzahlFilesGeadded)). Dann fliegt dir das ganze um die Ohren wegen dem was du da in der foreach() gemacht hast ...
Zuletzt geändert von padreigh am 13. Oktober 2010 18:18, insgesamt 1-mal geändert.
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

padreigh hat geschrieben:Davon mal abgesehen ... was glaubst du was passiert mit jeder einzelnen "source" wenn du die {} verlässt? Stichwort: SCOPE, HEAP, STACK.

Versuch mal

Code: Alles auswählen

Phonon::MediaSource * newSource = new Phonon::MediaSource(filename);
neuerMember_QListOfMediaSourceS.append(newSource);
Errm, sources ist eine QList<Phonon::MediaSource>, und da ist der Scope egal, es kommt sowieso eine Kopie da rein.

Code: Alles auswählen

        }
        if (!sources.isEmpty()){
            metaInformationResolver->setCurrentSource(sources.at(index));
        }
}
Damit setzt du das ganze auf die !!vorherige!! größe der sources ... also auf was was vor dem Slot schon drin war ... war nix drin gibts kein ärger (da empty, if verhindert das), war was drin gibts noch keinen Ärger, würde aber sobald du versuchst auf etwas zuzugreifen das bei index+x in sources liegt (x in (1..AnzahlFilesGeadded)). Dann fliegt dir das ganze um die Ohren wegen dem was du da in der foreach() gemacht hast ...
Höh? Nö. Im Original-example schaut das so aus:

Code: Alles auswählen

void MainWindow::addFiles()
{
    QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Music Files"), 
        QDesktopServices::storageLocation(QDesktopServices::MusicLocation));

    if (files.isEmpty())
        return;

    int index = sources.size();
    foreach (QString string, files) {
            Phonon::MediaSource source(string);
        
        sources.append(source);
    } 
    if (!sources.isEmpty())
        metaInformationResolver->setCurrentSource(sources.at(index));

}
Wenn keine files ausgewählt -> return - das ist entscheidend und sollte vom OP übernommen werden. Ansonsten setzt die letzte Zeile die currentSource auf die erste der neu hinzugefügten - kein Problem, solange auch files ausgewählt wurden, und da versichert man sich ja mit dem return.
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

Beitrag von thebigear »

Die Antworten sind ja alle ganz schön und gut, aber sie lösen leider nicht mein Problem.

@padreigh: der code hier war erstmal aus meinem debug-mode und problem verstehen modus und noch kein fertiger release-code...

Das Probelm ist aber, dass ich durch die zeile:

Code: Alles auswählen

void kannotate::metaStateChanged(Phonon::State newState, Phonon::State oldState){ 
...
  if(sources.size() < index){
        metaInformationResolver->setCurrentSource(sources.at(index));
    }
...
nicht nochmal in den Slot gelange!!!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

thebigear hat geschrieben:Das Probelm ist aber, dass ich durch die zeile:

Code: Alles auswählen

void kannotate::metaStateChanged(Phonon::State newState, Phonon::State oldState){ 
...
  if(sources.size() < index){
        metaInformationResolver->setCurrentSource(sources.at(index));
    }
...
nicht nochmal in den Slot gelange!!!
Und die Lösung hab ich doch schon gesagt: "<" != ">". Im Original steht da

Code: Alles auswählen

    if (sources.size() > index) {
        metaInformationResolver->setCurrentSource(sources.at(index));
    }
Wenn ich dort das > gegen ein < austausch entsteht das selbe Verhalten.
Die Logik dahinter darfst du aber jetzt selber suchen ;)
padreigh
Beiträge: 340
Registriert: 13. Mai 2010 10:06

Beitrag von padreigh »

padreigh hat geschrieben:
das war dann wohl ein Griff ins Klo :oops: setzen 5, sorry.
franzf hat geschrieben: [snipp code]
Errm, sources ist eine QList<Phonon::MediaSource>, und da ist der Scope egal, es kommt sowieso eine Kopie da rein.

Höh? Nö. Im Original-example schaut das so aus:
[snipp code]
Wenn keine files ausgewählt -> return - das ist entscheidend und sollte vom OP übernommen werden. Ansonsten setzt die letzte Zeile die currentSource auf die erste der neu hinzugefügten - kein Problem, solange auch files ausgewählt wurden, und da versichert man sich ja mit dem return.
jupp stimmt, war wohl nicht ganz bei der Sache ... ich kann das ganze Phonon zeug leider nicht testen da es bei mir nicht funktioniert

(das example zB zeigt zwar alles an, drücke ich auf Play rauscht der aber in 5 Sekunden durch die ganze Liste durch :/ obwohl ich gstreamer installiert habe ... (lucid,Qt4.6))
Patrick (QtCreator 1.3.1, Qt 4.6.3)
---
template = subdirs
thebigear
Beiträge: 17
Registriert: 29. März 2010 15:36

Beitrag von thebigear »

@franzf UPS das hatte ich übersehen. Tja so kanns kommen. Sorry, jetzt, mit dem umgedrehten Zeichen klappts auch.

Danke
Antworten