Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

OSX and librt



  • Hi all,

    EDIT: If it matters, it's OSX 10.6.3 (32 bit). I built QT static from source with the macx-g++ platform and in release and opensource modes.

    I wrote a command line program to add ID3 Tags to MP3s using the TabLib library and QT 4.8. It's for my Firefox Plugin YoutubeMP3Podcaster. It's sort of a crazy hack to get around a Firefox limitation. I pass the path to an MP3 in as a URL Encoded string and use QUrl to decode it and QString to turn it into a UTF8 String suitable for TabLib.

    It works great on Windows and LInux, but for some reason QT wants librt.a (the POSIX realtime Library), and it's not implemented on OSX, so trying to build with

    g++ ./encMP3Tagger.cpp -o encMP3Tagger.exe -L/use/local/lib/ -I/usr/local/include/taglib -ltag -lPocoFoundation -lPocoUtil -lPocoXML -lPocoNet llvm-config --libs core llvm-config --ldflags -lQtCore -ldl -lrt -lz

    Just gets me a nice big error about librt not being available.

    I'm only using QString and QUrl though, so I can't imagine why it needs the realtime clock functions. I've found a bunch of hacks where people replace the librt calls, but I'm trying to avoid hacking into the QT code and my C++ skills are a bit weak :P.

    Does anyone know a painless solution to get my code to build on OSX?

    Here's the source

    @
    #define TAGLIB_STATIC
    #include <iostream>
    #include <string.h>
    #include <fstream>

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <stdlib.h>

    #include "tlist.h"
    #include "fileref.h"
    #include "tfile.h"
    #include "tag.h"
    #include "id3v2tag.h"
    #include "mpegfile.h"

    #include <QtCore/QString>
    #include <QtCore/QUrl>

    using namespace std;
    using namespace TagLib;

    bool isArgument(const char *s)
    {
    return strlen(s) == 2 && s[0] == '-';
    }

    bool isFile(const char *s)
    {
    struct stat st;
    #ifdef _WIN32
    return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG));
    #else
    return ::stat(s, &st) == 0 && (st.st_mode & (S_IFREG | S_IFLNK));
    #endif
    }

    void usage()
    {
    cout << endl;
    cout << "Usage: tagwriter <fields> <files>" << endl;
    cout << endl;
    cout << "Where the valid fields are:" << endl;
    cout << " -t <title>" << endl;
    cout << " -a <artist>" << endl;
    cout << " -A <album>" << endl;
    cout << " -c <comment>" << endl;
    cout << " -g <genre>" << endl;
    cout << " -y <year>" << endl;
    cout << " -T <track>" << endl;
    cout << endl;
    exit(1);
    }

    int main(int argc, char *argv[])
    {

    TagLib::ListTagLib::FileRef fileList;
    QString filepath( argv[argc - 1] );
    QString url = QUrl::fromPercentEncoding( filepath.toUtf8() );
    TagLib::FileRef f( url.toUtf8().constData() );

    if(!f.isNull() && f.tag())
    fileList.append(f);

    argc--;

    if(fileList.isEmpty())
    usage();

    for(int i = 1; i < argc - 1; i += 2) {

    if(isArgument(argv[i]) && i + 1 < argc && !isArgument(argv[i + 1])) {
    

    char field = argv[i][1];

    QString qValue = QUrl::fromPercentEncoding( argv[i + 1] );

    TagLib::String value ( qValue.toUtf8().constData(), TagLib::String::UTF8);

    TagLib::ListTagLib::FileRef::Iterator it;

    for(it = fileList.begin(); it != fileList.end(); ++it) {

        TagLib::Tag *t = (*it).tag();
        
        switch (field) {
        case 't':
          t->setTitle(value);
          break;
        case 'a':
          t->setArtist(value);
          break;
        case 'A':
          t->setAlbum(value);
          break;
        case 'c':
          t->setComment(value);
          break;
        case 'g':
          t->setGenre(value);
          break;
        case 'y':
          t->setYear(value.toInt());
          break;
        case 'T':
          t->setTrack(value.toInt());
          break;
        default:
          usage();
          break;
        }//END SWITCH STATEMENT*/
    
      }//END FOR LOOP
    }else
      usage();
    

    }//end if-else

    TagLib::ListTagLib::FileRef::Iterator it;
    for(it = fileList.begin(); it != fileList.end(); ++it){
    //cout << "Saving a Tag" << endl;
    TagLib::MPEG::File mpegFile = (TagLib::MPEG::File)(*it).file();
    mpegFile->save(MPEG::File::AllTags, true, 3);
    //(*it).file()->save();

    }

    return 0;
    }//END MAIN
    @


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    Are you using a pro file handle your project ?



  • Nope, just a straight up compile with g++. It's so simple I didn't even bother with a make file :)


  • Lifetime Qt Champion

    You should when using Qt, it sets up the dependencies needed by Qt and avoids to make exe files on OS that don't have them ;)



  • Cool, the odd thing is I don't seem to have gotten qmake in my build from the qt-anywhere sources. I'm going to rebuild with qt 5 and give it anther go. I need to build static and as far as I can tell everything else builds dynamic.


  • Lifetime Qt Champion

    find -name qmake in your build folder should show that. If you did a make install, it should be in /usr/Trolltech/Qt_version_number/bin/



  • :P, I hate to admit it but I've given up on QT on mac. I managed to get the poco library to work on mac (Windows doesn't like it so much). It's a hassle though since now I've got 2 code bases. When I get some free time (ha ha) I might go back and give it another go :) Thanks again!


Log in to reply