Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1181 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  Projet de lecture RFID + GUI

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Projet de lecture RFID + GUI

n°2197101
wizardman
Posté le 10-07-2013 à 18:40:16  profilanswer
 

Bonjour à tous,
 
Je travaille actuellement sur un projet qui permettrai de lancer la lecture d'un album de musique (pour commencer) à la suite de la lecture d'un tag RFID.
 
De façon à le rendre le plus souple possible, je me suis tourné vers le C++ et la bibliothèque Qt 5.1.0 pour l'interface utilisateur, ainsi que AppleScript pour controler iTunes qui sera le premier lecteur média (d'autres plus tard si possible). J'ai quelques notions de C++ mais je me considère débutant. Néanmoins, cela ne devrait pas poser trop de problèmes dans un premier temps.
 
On considèrera qu'il existe déjà une base de données mettant en relation des numéros de tag RFID avec des identifiants d'albums (ou de morceaux) dans iTunes.
 
La logique d'action est la suivante :
- Lecture du tag RFID
- Recherche de l'album correspondant à l'identifiant RFID
- Exécution de la commande AppleScript qui lance l'album correspondant sur iTunes
 
Que pensez-vous du choix des différents éléments pour ce projet (C++, Qt 5.1.0, AppleScript) ?
 
Je développe sous Mac OS X Snow Leopard (10.6.8) avec Xcode 4.2 (par défaut), est-ce également un bon choix ? Existe-t-il une solution plus optimale ?
Sachant que j'ai déjà quelques soucis pour y linker Qt (il ne trouve tout simplement pas les librairies lors de la compilation, apparemment une histoire de PATH). Je ne vois pas où configurer le chemin vers Qt (néanmoins cela fonctionne très bien dans Qt Creator).
 
Je compte y aller par petits bouts, j'ai déjà trifouillé l'AppleScript (récupérer la liste des albums, lancer un morceau, etc.), également l'exécution du script via C++, et je pense ajouter les fonctionnalités au fur et à mesure de mon apprentissage.
 
Vos avis et recommandations me seraient très précieux :)

mood
Publicité
Posté le 10-07-2013 à 18:40:16  profilanswer
 

n°2197105
Farian
Posté le 10-07-2013 à 19:08:07  profilanswer
 

Bonjour !
 
Étant assez fan de Qt (que je pratique depuis 10 ans), je ne peux qu'approuver votre choix !
 
En revanche, n'ayant jamais travaillé sur Mac', je ne saurais guère vous conseiller au niveau du compilateur et/ou de l'API AppleScript.
 
Pour la configuration et les bibliothèques dynamiques, je confirme, c'est bien un problème de path (ou de DYLD_LIBRARY_PATH, en l'occurrence). En revanche, sous Linux, l'option "rpath" fonctionne avec g++, xcode ne la gère pas ?
 
Et, pour finir, concernant votre approche, rien de particulier à redire, une vision incrémentale me paraît tout à fait adaptée.
 
Bon courage et tenez nous au courant de votre progression !

n°2197453
wizardman
Posté le 14-07-2013 à 20:29:49  profilanswer
 

Cela semble bien fonctionner jusqu'alors sur Qt Creator, je pense donc rester dessus pour le moment.
J'ai appris presque par hasard que Qt propose bien plus que du fenêtrage, c'est pas mal du tout !
 
Ma première question est basique.
 
Je compte récupérer la liste des albums iTunes via un AppleScript :

Code :
  1. tell application "iTunes"
  2. set uniqueNames to {}
  3. set {albumName, artistName} to {album, artist} of every track
  4. repeat with i from 1 to count albumName
  5.  set trackInfo to item i of albumName & ";" & item i of artistName
  6.  if trackInfo is not in uniqueNames then
  7.   copy trackInfo to beginning of uniqueNames
  8.  end if
  9. end repeat
  10. return reverse of uniqueNames
  11. end tell


 
Ça me sort donc une liste des albums et des artistes associés (du style {"Album 1;Artiste 1", "Album 2; Artiste 2", etc}).
 
Pour la récupérer dans mon programme C++, puis-je utiliser une commande (QProcess::execute() par exemple) ou dois-je la stocker dans un fichier que je lis ensuite avec le programme ?
Dans le cas de QProcess::execute(), la fonction retourne -2, -1 ou 0, mais puis-je récupérer la sortie d'une commande système via cette fonction ?


Message édité par wizardman le 14-07-2013 à 20:30:25
n°2197454
theshockwa​ve
I work at a firm named Koslow
Posté le 14-07-2013 à 20:46:41  profilanswer
 

Ton programme n'aura jamais besoin de tourner sur une machine qui ne soit pas Apple ?
Parce que je soupçonne que l'AppleScript ne fonctionne pas top pour dialoguer avec un iTunes sous windows ... Peut-être que je me trompe, cela dit.
De même, je trouve la dépendance forte vers un lecteur de musique spécifique un peu contraignante, mais ca, c'est aussi notamment une question de goût.


---------------
last.fm
n°2197460
wizardman
Posté le 14-07-2013 à 22:39:03  profilanswer
 

theshockwave a écrit :

Ton programme n'aura jamais besoin de tourner sur une machine qui ne soit pas Apple ?
Parce que je soupçonne que l'AppleScript ne fonctionne pas top pour dialoguer avec un iTunes sous windows ... Peut-être que je me trompe, cela dit.
De même, je trouve la dépendance forte vers un lecteur de musique spécifique un peu contraignante, mais ca, c'est aussi notamment une question de goût.


 
En effet, si je souhaite le distribuer, il faudra que je l'adapte pour les autres systèmes et lecteurs, car pas d'AppleScript sous Windows par exemple.
Mais mon niveau en C++ est encore trop faible pour déjà me soucier de portabilité et d'API, si j'arrive à mener à bien ce projet pour qu'il fonctionne chez moi ce sera déjà un grand pas :ange:
Je peux par contre m'efforcer de développer le truc de sorte à ce qu'il soit modulable et donc pouvoir facilement ajouter un nouveau lecteur...

n°2198499
wizardman
Posté le 23-07-2013 à 14:56:27  profilanswer
 

J'ai un petit soucis avec mon parser XML.
 
J'utilise QtXML sur cet extrait de la librairie iTunes (qui n'utilise pas vraiment XML de façon standard comme vous le remarquerez), ce qui me permet de pouvoir trouver la liste des albums iTunes toutes plateformes confondues sans passer par AppleScript.
J'ai modifié le nom de certains tags pour pouvoir les repérer dans la sortie.
 
La logique est la suivante : j'analyse tous les tags et leurs enfants (et leurs enfants, etc) jusqu'à trouver un <key> qui contient Album, auquel cas j'affiche le contenu du tag suivant qui contient le nom de l'album en question.
 
Voici mon code :
 

Code :
  1. #include <iostream>
  2. #include <QtCore>
  3. #include <QFile>
  4. #include <QtXml>
  5. using namespace std;
  6. void parse(QDomNode n) {
  7. while(!n.isNull()) {
  8.  // If the node has children
  9.  if(n.hasChildNodes() && !n.isNull()) {
  10.   // We get the children
  11.   QDomNodeList nChildren = n.childNodes();
  12.   // We print the current tag name
  13.   std::cout << "[~] Current tag : <" << qPrintable(n.toElement().tagName()) << ">" << std::endl;
  14.   // And for each sub-tag of the current tag
  15.   for(int i = 0; i < nChildren.count(); i++) {
  16.    // We get the children node
  17.    QDomNode nChild = nChildren.at(i);
  18.    // And the tag value (we're looking for *Album* here)
  19.    QString tagValue = nChild.toElement().text();
  20.    // If the tag isn't null and contain *Album*
  21.    if(!nChild.isNull() && tagValue == "Album" ) {
  22.     // The album name is in the next tag
  23.     QDomElement albumNode = nChild.nextSiblingElement();
  24.     std::cout << "[-] Album found -> " << qPrintable(albumNode.text()) << std::endl;
  25.    }
  26.    // And we parse the children node
  27.    parse(nChild);
  28.   }
  29.  }
  30.  n = n.nextSibling();
  31. }
  32. }
  33. int main() {
  34. QDomDocument doc("Lib" );
  35. QFile file("/Users/wizardman/QtRFIDMusic/Lib.min.xml" );
  36. if(!file.open(QIODevice::ReadOnly))
  37.  return 1;
  38. if(!doc.setContent(&file)) {
  39.  file.close();
  40.  return 1;
  41. }
  42. file.close();
  43. // Root element
  44. QDomElement docElem = doc.documentElement();
  45. // <plist> -> <dict>
  46. QDomNode n = docElem.firstChild().firstChild();
  47. cout << endl << "Album list" << endl;
  48. cout << "------------------------------------" << endl;
  49. parse(n);
  50. return 0;
  51. }


 
Et voici ma sortie...
En commentant la ligne qui indique le tag analysé, je souhaiterai que le programme ne me sorte que les deux albums listés dans le XML.
 
Je n'arrive pas à comprendre pourquoi il tourne en boucle, j'ai l'impression de faire tous les tests nécessaires pour ne séléctionner que ce que je cherche.
Des idées ?

Message cité 1 fois
Message édité par wizardman le 23-07-2013 à 14:57:48
n°2198595
Farian
Posté le 24-07-2013 à 11:33:09  profilanswer
 

wizardman a écrit :

J'ai un petit soucis avec mon parser XML.
 
J'utilise QtXML sur cet extrait de la librairie iTunes (qui n'utilise pas vraiment XML de façon standard comme vous le remarquerez), ce qui me permet de pouvoir trouver la liste des albums iTunes toutes plateformes confondues sans passer par AppleScript.
J'ai modifié le nom de certains tags pour pouvoir les repérer dans la sortie.
 
La logique est la suivante : j'analyse tous les tags et leurs enfants (et leurs enfants, etc) jusqu'à trouver un <key> qui contient Album, auquel cas j'affiche le contenu du tag suivant qui contient le nom de l'album en question.
 
...
Je n'arrive pas à comprendre pourquoi il tourne en boucle, j'ai l'impression de faire tous les tests nécessaires pour ne séléctionner que ce que je cherche.
Des idées ?


 
Bonjour !  
 
Plutôt que de continuer à chercher ce qui ne va pas dans votre code, je suis reparti d'un vieux code de parsing DOM que j'avais écrit il y a 10 ans (!)  et que j'ai adapté pour l'occasion :  
 

Code :
  1. void parse(const QDomElement& element)
  2. {
  3.     for(QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling())
  4.     {
  5.         QDomElement elementFils = n.toElement();
  6.         if (!elementFils.isNull())
  7.         {
  8.             QString tagValue = elementFils.tagName();
  9.             if (tagValue == "key" && elementFils.text() == "Album" )
  10.             {
  11.                 qDebug() << n.nextSiblingElement().text();
  12.             }
  13.             parse(elementFils);
  14.         }
  15.     }
  16. }


 
qui est appelée ainsi :  

Code :
  1. ...
  2.     QDomElement docElem = doc.documentElement();
  3.     // <plist> -> <dict>
  4.     qDebug() << "Album list" ;
  5.     qDebug() << "------------------------------------" ;
  6.     parse(docElem);
  7. ...


 
Le résultat est satisfaisant :  

Code :
  1. Album list
  2. ------------------------------------
  3. "J Dilla - Legacy Vol.1"
  4. "J Dilla - Legacy Vol.2"


 
(je ne m'explique pas les sauts de ligne ... et la flemme de chercher ou de tester en dehors de QtCreator :) )
 
Ensuite, j'ai tenté une approche plus ambitieuse, qui récupère pour chaque album toutes les infos dans une map (clé, valeur) :  
 

Code :
  1. void parseAlbum(const QDomElement& element, QMap<QString, QString>& album)
  2. {
  3.     QString cle;
  4.     for(QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling())
  5.     {
  6.         QDomElement elementFils = n.toElement();
  7.         if (!elementFils.isNull())
  8.         {
  9.             QString tagValue = elementFils.tagName();
  10.             if (elementFils.tagName().startsWith("key" ))
  11.             {
  12.                 cle = elementFils.text();
  13.             }
  14.             else
  15.             {
  16.                 album[cle] = elementFils.text();
  17.             }
  18.         }
  19.     }
  20. }
  21. void parseAlbums(const QDomElement& element, QList<QMap<QString, QString> >& albums)
  22. {
  23.     for(QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling())
  24.     {
  25.         QDomElement elementFils = n.toElement();
  26.         if (!elementFils.isNull())
  27.         {
  28.             if (elementFils.tagName().startsWith("dict_FOCUS" ))
  29.             {
  30.                 QMap<QString, QString> album;
  31.                 parseAlbum(elementFils, album);
  32.                 if (album.size() > 0)
  33.                 {
  34.                     albums << album;
  35.                 }
  36.             }
  37.             else
  38.             {
  39.                 parseAlbums(elementFils, albums);
  40.             }
  41.         }
  42.     }
  43. }


 
l'appel et l'affichage se faisant ainsi :  

Code :
  1. ...
  2.     QDomElement docElem = doc.documentElement();
  3.     QList<QMap<QString, QString> > albums;
  4.     parseAlbums(docElem, albums);
  5.     QMap<QString, QString> album;
  6.     foreach (album, albums)
  7.     {
  8.         qDebug() << "Album :";
  9.         foreach (QString cle, album.keys())
  10.         {
  11.             qDebug() << "\t" << cle << ":" << album[cle];
  12.         }
  13.     }
  14.     ...


 
On obtient alors :  

Code :
  1. Album :
  2.  "Album" : "J Dilla - Legacy Vol.1"
  3.  "Artist" : "1st Down"
  4.  "Bit Rate" : "192"
  5.  "Comments" : "FEFE2003"
  6.  "Date Added" : "2010-11-03T21:01:56Z"
  7.  "Date Modified" : "2010-06-25T16:49:08Z"
  8.  "File Folder Count" : "5"
  9.  "Genre" : "Hip-Hop"
  10.  "Kind" : "Fichier audio MPEG"
  11.  "Library Folder Count" : "1"
  12.  "Location" : "file://localhost/Users/wizardman/Music/iTunes/iTunes%20Media/Music/1st%20Down/J%20Dilla%20-%20Legacy%20Vol.1/40%20No%20Place%20To%20Go.mp3"
  13.  "Name" : "No Place To Go"
  14.  "Persistent ID" : "BE4ED29CCB7ED086"
  15.  "Sample Rate" : "44100"
  16.  "Size" : "4409344"
  17.  "Skip Count" : "1"
  18.  "Skip Date" : "2012-12-14T14:31:18Z"
  19.  "Total Time" : "183666"
  20.  "Track ID" : "3456"
  21.  "Track Number" : "40"
  22.  "Track Type" : "File"
  23.  "Year" : "2006"
  24. Album :
  25.  "Album" : "J Dilla - Legacy Vol.2"
  26.  "Artist" : "1st Down"
  27.  "Bit Rate" : "192"
  28.  "Comments" : "FEFE2003"
  29.  "Date Added" : "2010-11-03T21:01:56Z"
  30.  "Date Modified" : "2010-06-25T16:49:08Z"
  31.  "File Folder Count" : "5"
  32.  "Genre" : "Hip-Hop"
  33.  "Kind" : "Fichier audio MPEG"
  34.  "Library Folder Count" : "1"
  35.  "Location" : "file://localhost/Users/wizardman/Music/iTunes/iTunes%20Media/Music/1st%20Down/J%20Dilla%20-%20Legacy%20Vol.1/40%20No%20Place%20To%20Go.mp3"
  36.  "Name" : "No Place To Go"
  37.  "Persistent ID" : "BE4ED29CCB7ED086"
  38.  "Sample Rate" : "44100"
  39.  "Size" : "4409344"
  40.  "Skip Count" : "1"
  41.  "Skip Date" : "2012-12-14T14:31:18Z"
  42.  "Total Time" : "183666"
  43.  "Track ID" : "3456"
  44.  "Track Number" : "40"
  45.  "Track Type" : "File"
  46.  "Year" : "2006"


 
Et vous pouvez ensuite accéder directement aux champs qui vous intéressent, par exemple l'affichage de l'artiste du nom de tous les albums :  
 

Code :
  1. ...
  2.     QDomElement docElem = doc.documentElement();
  3.     QList<QMap<QString, QString> > albums;
  4.     parseAlbums(docElem, albums);
  5.     QMap<QString, QString> album;
  6.     foreach (album, albums)
  7.     {
  8.         qDebug() << "Album : " << album["Album"] << "par : " << album["Artist"];
  9.     }
  10.     ...


 
Bonne continuation !

n°2198651
rufo
Pas me confondre avec Lycos!
Posté le 24-07-2013 à 17:11:04  profilanswer
 

Juste une proposition pour le pb de portabilité, je me disais que Java aurait été un choix peut-être plus judicieux; restait le pb du "pilotage" d'itunes. Après une rapide recherche sur Google "java iTunes", il semblerait qu'il existe une API pour java permettant de piloter iTunes :
http://code.google.com/p/java-itunes-api/wiki/Welcome  ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
n°2198663
theshockwa​ve
I work at a firm named Koslow
Posté le 24-07-2013 à 18:08:43  profilanswer
 

rufo a écrit :

Juste une proposition pour le pb de portabilité, je me disais que Java aurait été un choix peut-être plus judicieux; restait le pb du "pilotage" d'itunes. Après une rapide recherche sur Google "java iTunes", il semblerait qu'il existe une API pour java permettant de piloter iTunes :
http://code.google.com/p/java-itunes-api/wiki/Welcome  ;)


 
mais apparamment, cette API est seulement pour OSX [:petrus75]


---------------
last.fm
n°2198668
wizardman
Posté le 24-07-2013 à 18:51:01  profilanswer
 

Merci Farian pour tes recherches. Elles m'ont permis, avec une aide sur Stackoverflow, d'en venir au code suivant en abandonnant la récursivité et en allant directement cherche le tag qui m'intéresse :
 

Code :
  1. #include <iostream>
  2. #include <QtCore>
  3. #include <QFile>
  4. #include <QtXml>
  5. #include <QtDebug>
  6. #include <QVector>
  7. using namespace std;
  8. int main() {
  9. QDomDocument doc("Lib" );
  10. QFile file("/Users/wizardman/QtRFIDMusic/Lib.xml" );
  11. if(!file.open(QIODevice::ReadOnly))
  12.  return 1;
  13. if(!doc.setContent(&file)) {
  14.  file.close();
  15.  return 1;
  16. }
  17. file.close();
  18. // Root element
  19. QDomElement docElem = doc.documentElement();
  20. // <plist> -> <dict>
  21. QDomNode n = docElem.firstChild().firstChildElement("dict" );
  22. cout << endl << "Album list" << endl;
  23. cout << "------------------------------------" << endl;
  24. QVector<QString> albums;
  25. QDomNodeList list = n.childNodes();
  26. int count = list.count();
  27. for(int i = 0; i < count; ++i) {
  28.  QDomElement node = list.at(i).toElement();
  29.  if(node.tagName().startsWith("dict" )) {
  30.   node = node.firstChildElement();
  31.   while(!node.isNull()) {
  32.    QString t = node.text();
  33.    if(node.text() == "Album" && node.tagName() == "key" ) {
  34.     node = node.nextSiblingElement();
  35.     if(!node.isNull() && node.tagName() == "string" ) {
  36.      QString album = node.text();
  37.      if(albums.indexOf(album) == -1)
  38.       albums.append(album);
  39.     }
  40.    }
  41.    node = node.nextSiblingElement();
  42.   }
  43.  }
  44. }
  45. qDebug() << albums;
  46. return 0;
  47. }


 
Rufo: peut-être oui, mais je ne suis vraiment pas familier de Java, et je préfère voir large avec le C++ qui est vraiment toutes plateformes pour le coup !


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  Projet de lecture RFID + GUI

 

Sujets relatifs
Installer un projet sous symfony 1.4.9 en LocalProjet VBA : Simulation d'un jeux de poker
comment lire une puce RFIDMigrer un projet de ruby 1.8.6 vers 2.0
projet en programme c en urgence !!cherche benevole pour projet ambicieux
lecture d'un fichier java .niowebmaster - Etudiants université de paris ( Bon projet)
Python et XBMC : récupérer le fichier en cours de lectureMini projet html/css/java HELP
Plus de sujets relatifs à : Projet de lecture RFID + GUI


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR