/* * amarok2-now-playing.cpp * * While designed for amarok 2 it also works for VLC: * "amarok2-now-playing vlc" * * or any other media player that implements the org.freedesktop.MediaPlayer * dbus interface e.g. audacious: * "amarok2-now-playing org.mpris.audacious" * * Use qdbus to get a list of dbus services and see what interfaces they * provide, "qdbus", "qdbus org.kde.amarok" etc. * * Compile with the usual commands (same as any library that uses pkg-config): * g++ -Wall -O2 -g `pkg-config --cflags QtCore QtDBus` `pkg-config --libs QtCore QtDBus` -o amarok2-now-playing amarok2-now-playing.cpp */ #include #include #include #include #include #include #include #include #include #include #include int main( int argc, char * argv[] ) { QCoreApplication coreapp( argc, argv ); QDBusConnection sessionbus = QDBusConnection::sessionBus(); if ( !sessionbus.isConnected() ) { fprintf(stderr,"Could not connect to session bus\n"); return 10; } QString program,service; if ( argc >= 2 ) { if ( QString::fromLocal8Bit(argv[1]) == "vlc" ) { service = QString::fromUtf8("org.mpris.vlc"); program = QString::fromUtf8("VLC"); } else if ( QString::fromLocal8Bit(argv[1]) == "amarok" ) { service = QString::fromUtf8("org.kde.amarok"); program = QString::fromUtf8("amarok"); } else { service = QString::fromLocal8Bit(argv[1]); program = service.mid( service.lastIndexOf('.') + 1 ); } } else { service = QString::fromUtf8("org.kde.amarok"); program = QString::fromUtf8("amarok"); } if ( service.isEmpty() ) { fprintf(stderr,"Empty service!\n"); return 5; } QString path = QString::fromUtf8("/Player"); QString interface = QString::fromUtf8("org.freedesktop.MediaPlayer"); QString method = QString::fromUtf8("GetMetadata"); QDBusMessage getmetadata = QDBusMessage::createMethodCall( service, path, interface, method ); QDBusMessage metadatamsg = sessionbus.call( getmetadata, QDBus::Block, 30*1000 ); if ( metadatamsg.type() != QDBusMessage::ReplyMessage ) { fprintf(stderr,"Unexpected reply type()=%d\n",metadatamsg.type()); fprintf(stderr,"errorMessage()='%s'\n",metadatamsg.errorMessage().toLocal8Bit().constData()); return 20; } QList args = metadatamsg.arguments(); if ( args.size() == 1 ) { QVariantMap varmap = qdbus_cast(args.first()); /* * amarok keys: * album * artist * arturl * audio-bitrate * audio-samplerate * comment * genre * location * mtime * rating * time * title * tracknumber * year */ #if 0 for ( QVariantMap::const_iterator it = varmap.constBegin(); it != varmap.constEnd(); ++ it ) { printf("key=%s\n",it.key().toLocal8Bit().constData()); } #endif QString artist = varmap.value("artist").toString(); QString title = varmap.value("title").toString(); if ( !(artist.isEmpty() || title.isEmpty()) ) { printf( "%s playing (%s - %s", program.toLocal8Bit().constData(), artist.toLocal8Bit().constData(), title.toLocal8Bit().constData() ); if ( varmap.contains("audio-bitrate") ) { printf(" - %dkbps)",varmap.value("audio-bitrate").toInt()); } else { printf(")"); } } else if ( varmap.contains("location") ) { /* amarok gives URI with %20 for space etc. while vlc just gives the file name and path */ QString uri = QUrl::fromPercentEncoding(varmap.value("location").toString().toUtf8()); QFileInfo fi(uri); printf( "%s playing (%s)", program.toLocal8Bit().constData(), fi.fileName().toLocal8Bit().constData() ); } else { fprintf(stderr,"Cannot find artist+title or file\n"); return 50; } if ( varmap.contains("time") || varmap.contains("length") ) { int length = 0; if ( varmap.contains("time") ) { length = varmap.value("time").toInt(); } else { length = varmap.value("length").toInt() / 1000; } QDBusMessage getpos = QDBusMessage::createMethodCall( service, path, interface, QString::fromUtf8("PositionGet") ); QDBusMessage posmsg = sessionbus.call( getpos, QDBus::Block, 30*1000 ); if ( (posmsg.type() == QDBusMessage::ReplyMessage) && (posmsg.arguments().size() == 1) ) { int pos = qdbus_cast(posmsg.arguments().first()); int len_h = length / (60*60); int len_m = (length - len_h * (60*60)) / (60); int len_s = length - (len_h * (60*60) + len_m * (60)); int pos_h = pos / (60*60*1000); int pos_m = (pos - pos_h * (60*60*1000)) / (60*1000); int pos_s = (pos - (pos_h * (60*60*1000) + pos_m * (60*1000))) / 1000; if ( len_h == 0 ) { printf( " - (%d:%02d/%d:%02d)\n", pos_m, pos_s, len_m, len_s ); } else { printf( " - (%d:%02d:%02d/%d:%02d:%02d)\n", pos_h, pos_m, pos_s, len_h, len_m, len_s ); } } else { printf("\n"); } } else { printf("\n"); } } else { fprintf(stderr,"Unexpected data received size()=%d\n",args.size()); return 40; } return 0; }