├── .gitignore ├── AirTV-Qt ├── AirTV.icns ├── AirTV.ico ├── AirTV.pro ├── AirTV.qrc ├── AirTV.rc ├── audiocallbacks.cpp ├── audiocallbacks.h ├── audiooutput.cpp ├── audiooutput.h ├── images │ └── airtv.svg ├── main.cpp ├── mainapplication.cpp ├── mainapplication.h ├── mainwindow.ui └── qtsingleapplication │ ├── INSTALL.TXT │ ├── README.TXT │ ├── buildlib │ └── buildlib.pro │ ├── common.pri │ ├── configure │ ├── configure.bat │ ├── doc │ ├── html │ │ ├── classic.css │ │ ├── images │ │ │ └── qt-logo.png │ │ ├── index.html │ │ ├── qtsingleapplication-example-loader.html │ │ ├── qtsingleapplication-example-trivial.html │ │ ├── qtsingleapplication-members.html │ │ ├── qtsingleapplication-obsolete.html │ │ ├── qtsingleapplication.dcf │ │ ├── qtsingleapplication.html │ │ ├── qtsingleapplication.index │ │ ├── qtsingleapplication.qhp │ │ ├── qtsinglecoreapplication-example-console.html │ │ ├── qtsinglecoreapplication-members.html │ │ └── qtsinglecoreapplication.html │ ├── images │ │ └── qt-logo.png │ └── index.qdoc │ ├── examples │ ├── console │ │ ├── console.pro │ │ ├── console.qdoc │ │ └── main.cpp │ ├── examples.pro │ ├── loader │ │ ├── file1.qsl │ │ ├── file2.qsl │ │ ├── loader.pro │ │ ├── loader.qdoc │ │ └── main.cpp │ └── trivial │ │ ├── main.cpp │ │ ├── trivial.pro │ │ └── trivial.qdoc │ ├── qtsingleapplication.pro │ └── src │ ├── QtLockedFile │ ├── QtSingleApplication │ ├── qtlocalpeer.cpp │ ├── qtlocalpeer.h │ ├── qtlockedfile.cpp │ ├── qtlockedfile.h │ ├── qtlockedfile_unix.cpp │ ├── qtlockedfile_win.cpp │ ├── qtsingleapplication.cpp │ ├── qtsingleapplication.h │ ├── qtsingleapplication.pri │ ├── qtsinglecoreapplication.cpp │ ├── qtsinglecoreapplication.h │ └── qtsinglecoreapplication.pri ├── LICENSE ├── Makefile.am ├── README.md ├── airport.key ├── autogen.sh ├── configure.ac ├── include ├── Makefile.am └── shairplay │ ├── airplay.h │ ├── dnssd.h │ └── raop.h ├── m4 └── pkg.m4 └── src ├── Makefile.am ├── audio.c ├── audio.h ├── bindings ├── python │ └── Shairplay.py └── qt4 │ ├── dnssdservice.cpp │ ├── dnssdservice.h │ ├── raopcallbackhandler.cpp │ ├── raopcallbackhandler.h │ ├── raopcallbacks.h │ ├── raopservice.cpp │ └── raopservice.h ├── lib ├── Makefile.am ├── aac_eld │ ├── Makefile.am │ ├── aac_eld.c │ └── aac_eld.h ├── airplay.c ├── alac │ ├── Makefile.am │ ├── alac.c │ ├── alac.h │ └── stdint_win.h ├── base64.c ├── base64.h ├── compat.h ├── crypto │ ├── Makefile.am │ ├── aes.c │ ├── aes_locl.h │ ├── bigint.c │ ├── bigint.h │ ├── bigint_impl.h │ ├── config.h │ ├── crypto.h │ ├── hmac.c │ ├── md5.c │ ├── new_aes.c │ ├── os_port.h │ ├── rc4.c │ └── sha1.c ├── digest.c ├── digest.h ├── dnssd.c ├── dnssd.m ├── dnssdint.h ├── fairplay.c ├── fairplay.h ├── global.h ├── http_parser.c ├── http_parser.h ├── http_request.c ├── http_request.h ├── http_response.c ├── http_response.h ├── httpd.c ├── httpd.h ├── logger.c ├── logger.h ├── memalign.h ├── netutils.c ├── netutils.h ├── raop.c ├── raop_buffer.c ├── raop_buffer.h ├── raop_rtp.c ├── raop_rtp.h ├── rsakey.c ├── rsakey.h ├── rsapem.c ├── rsapem.h ├── sdp.c ├── sdp.h ├── sockets.h ├── threads.h ├── utils.c └── utils.h ├── shairplay.c └── test ├── dnssd_test.c ├── dnssd_test.m ├── example.c ├── main.c └── test.py /.gitignore: -------------------------------------------------------------------------------- 1 | *-build-* 2 | *.user 3 | *.o 4 | *.DS_Store 5 | *.swp 6 | project.xcworkspace 7 | xcuserdata 8 | 9 | # autotools 10 | Makefile 11 | *.lo 12 | *.in 13 | .deps 14 | .libs 15 | *.la 16 | *.a 17 | m4/ 18 | missing 19 | libtool 20 | ltmain.sh 21 | install-sh 22 | depcomp 23 | configure 24 | config.* 25 | autom4te.cache 26 | aclocal.m4 27 | stamp-h1 28 | src/shairplay 29 | src/test/example 30 | 31 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/shairplay/247bfa850917aa004d53d7ce540f6d68f8950bce/AirTV-Qt/AirTV.icns -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/shairplay/247bfa850917aa004d53d7ce540f6d68f8950bce/AirTV-Qt/AirTV.ico -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2011-12-04T00:47:51 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui multimedia phonon svg 8 | 9 | include(qtsingleapplication/src/qtsingleapplication.pri) 10 | 11 | TARGET = AirTV 12 | TEMPLATE = app 13 | ICON = AirTV.icns 14 | RC_FILE = AirTV.rc 15 | 16 | win32 { 17 | LIBS += C:\\QtSDK\\mingw\\lib\\libws2_32.a 18 | QMAKE_LFLAGS += -static-libgcc 19 | } 20 | macx { 21 | QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.5 22 | } 23 | 24 | LIBS += -lshairplay 25 | INCLUDEPATH += ../src/include/ ../src/bindings/qt4/ 26 | SOURCES += main.cpp\ 27 | ../src/bindings/qt4/raopservice.cpp \ 28 | ../src/bindings/qt4/raopcallbackhandler.cpp \ 29 | ../src/bindings/qt4/dnssdservice.cpp \ 30 | audiooutput.cpp \ 31 | mainapplication.cpp \ 32 | audiocallbacks.cpp 33 | 34 | HEADERS += \ 35 | ../src/bindings/qt4/raopservice.h \ 36 | ../src/bindings/qt4/raopcallbacks.h \ 37 | ../src/bindings/qt4/raopcallbackhandler.h \ 38 | ../src/bindings/qt4/dnssdservice.h \ 39 | audiooutput.h \ 40 | mainapplication.h \ 41 | audiocallbacks.h 42 | 43 | FORMS += mainwindow.ui 44 | 45 | RESOURCES += \ 46 | AirTV.qrc 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/airtv.svg 4 | 5 | 6 | -------------------------------------------------------------------------------- /AirTV-Qt/AirTV.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON DISCARDABLE "AirTV.ico" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/audiocallbacks.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include "audiocallbacks.h" 16 | 17 | AudioCallbacks::AudioCallbacks(QObject *parent) : 18 | RaopAudioHandler(parent) 19 | { 20 | } 21 | 22 | void * AudioCallbacks::audioInit(int bits, int channels, int samplerate) 23 | { 24 | AudioOutput *audioOutput = new AudioOutput(0); 25 | audioOutput->init(bits, channels, samplerate); 26 | audioOutput->start(); 27 | m_outputList.append(audioOutput); 28 | return audioOutput; 29 | } 30 | 31 | void AudioCallbacks::audioProcess(void *session, const QByteArray & buffer) 32 | { 33 | AudioOutput *audioOutput = (AudioOutput*)session; 34 | audioOutput->output(buffer); 35 | } 36 | 37 | void AudioCallbacks::audioDestroy(void *session) 38 | { 39 | AudioOutput *audioOutput = (AudioOutput*)session; 40 | m_outputList.removeAll(audioOutput); 41 | 42 | audioOutput->stop(); 43 | delete audioOutput; 44 | } 45 | 46 | 47 | void AudioCallbacks::audioFlush(void *session) 48 | { 49 | AudioOutput *audioOutput = (AudioOutput*)session; 50 | audioOutput->flush(); 51 | } 52 | 53 | void AudioCallbacks::audioSetVolume(void *session, float volume) 54 | { 55 | AudioOutput *audioOutput = (AudioOutput*)session; 56 | audioOutput->setVolume(volume); 57 | } 58 | 59 | -------------------------------------------------------------------------------- /AirTV-Qt/audiocallbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef AUDIOCALLBACKS_H 16 | #define AUDIOCALLBACKS_H 17 | 18 | #include "raopcallbacks.h" 19 | 20 | #include "audiooutput.h" 21 | 22 | class AudioCallbacks : public RaopAudioHandler 23 | { 24 | Q_OBJECT 25 | public: 26 | explicit AudioCallbacks(QObject *parent = 0); 27 | 28 | virtual void *audioInit(int bits, int channels, int samplerate); 29 | virtual void audioSetVolume(void *session, float volume); 30 | virtual void audioProcess(void *session, const QByteArray &buffer); 31 | virtual void audioFlush(void *session); 32 | virtual void audioDestroy(void *session); 33 | 34 | 35 | private: 36 | QList m_outputList; 37 | 38 | signals: 39 | 40 | public slots: 41 | 42 | }; 43 | 44 | #endif // AUDIOCALLBACKS_H 45 | -------------------------------------------------------------------------------- /AirTV-Qt/audiooutput.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef AUDIOOUTPUT_H 16 | #define AUDIOOUTPUT_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | class AudioOutput : public QIODevice 27 | { 28 | Q_OBJECT 29 | public: 30 | explicit AudioOutput(QObject *parent = 0); 31 | bool init(int bits, int channels, int samplerate); 32 | bool setDevice(QAudioDeviceInfo deviceInfo); 33 | 34 | void start(); 35 | void setVolume(float volume); 36 | void output(const QByteArray & data); 37 | void flush(); 38 | void stop(); 39 | 40 | qint64 readData(char *data, qint64 maxlen); 41 | qint64 writeData(const char *data, qint64 len); 42 | qint64 bytesAvailable() const; 43 | bool isSequential() const; 44 | 45 | private: 46 | void reinit(); 47 | 48 | private: 49 | bool m_initialized; 50 | QByteArray m_buffer; 51 | QAudioFormat m_format; 52 | QAudioDeviceInfo m_deviceInfo; 53 | QAudioOutput* m_output; 54 | float m_volume; 55 | 56 | signals: 57 | 58 | public slots: 59 | 60 | private slots: 61 | void notified(); 62 | void stateChanged(QAudio::State state); 63 | }; 64 | 65 | #endif // AUDIOOUTPUT_H 66 | -------------------------------------------------------------------------------- /AirTV-Qt/main.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #include "mainapplication.h" 19 | #include "videowidget.h" 20 | #include "raopservice.h" 21 | 22 | int main(int argc, char *argv[]) 23 | { 24 | QtSingleApplication a(argc, argv); 25 | if (a.isRunning()) { 26 | return 0; 27 | } 28 | a.setApplicationName("AirTV"); 29 | 30 | if (!QSystemTrayIcon::isSystemTrayAvailable()) { 31 | QMessageBox::critical(0, QObject::tr("Systray"), 32 | QObject::tr("I couldn't detect any system tray " 33 | "on this system.")); 34 | return 1; 35 | } 36 | QApplication::setQuitOnLastWindowClosed(false); 37 | 38 | MainApplication m; 39 | QObject::connect(&m, SIGNAL(quitRequested()), &a, SLOT(quit())); 40 | QObject::connect(&a, SIGNAL(aboutToQuit()), &m, SLOT(aboutToQuit())); 41 | 42 | if(m.start()) { 43 | return a.exec(); 44 | } else { 45 | return EXIT_FAILURE; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /AirTV-Qt/mainapplication.cpp: -------------------------------------------------------------------------------- 1 | #include "mainapplication.h" 2 | 3 | #include 4 | #include 5 | 6 | MainApplication::MainApplication(QObject *parent) : 7 | QObject(parent) 8 | { 9 | raopService = new RaopService(0); 10 | dnssdService = new DnssdService(0); 11 | trayIconMenu = new QMenu(0); 12 | 13 | quitAction = new QAction(tr("&Quit"), trayIconMenu); 14 | connect(quitAction, SIGNAL(triggered()), this, SIGNAL(quitRequested())); 15 | trayIconMenu->addAction(quitAction); 16 | 17 | // Construct the actual system tray icon 18 | trayIcon = new QSystemTrayIcon(this); 19 | trayIcon->setContextMenu(trayIconMenu); 20 | trayIcon->setIcon(QIcon(":icons/airtv.svg")); 21 | } 22 | 23 | MainApplication::~MainApplication() 24 | { 25 | trayIcon->setContextMenu(0); 26 | delete trayIconMenu; 27 | delete raopService; 28 | } 29 | 30 | bool MainApplication::start() 31 | { 32 | // Initialize the service 33 | bool initSuccess = false; 34 | initSuccess = raopService->init(10, &m_callbacks); 35 | if(!initSuccess) { 36 | qDebug() << "Error initializing raop service"; 37 | return false; 38 | } 39 | initSuccess &= dnssdService->init(); 40 | if(!initSuccess) { 41 | qDebug() << "Error initializing dnssd service"; 42 | return false; 43 | } 44 | 45 | char chwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 46 | QByteArray hwaddr(chwaddr, sizeof(chwaddr)); 47 | 48 | raopService->start(5000, hwaddr); 49 | dnssdService->registerRaop("Shairplay", 5000, hwaddr); 50 | trayIcon->show(); 51 | return true; 52 | } 53 | 54 | void MainApplication::stop() 55 | { 56 | dnssdService->unregisterRaop(); 57 | raopService->stop(); 58 | trayIcon->hide(); 59 | } 60 | 61 | void MainApplication::aboutToQuit() 62 | { 63 | this->stop(); 64 | } 65 | -------------------------------------------------------------------------------- /AirTV-Qt/mainapplication.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef MAINAPPLICATION_H 16 | #define MAINAPPLICATION_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "raopservice.h" 24 | #include "dnssdservice.h" 25 | #include "audiocallbacks.h" 26 | 27 | class MainApplication : public QObject 28 | { 29 | Q_OBJECT 30 | public: 31 | explicit MainApplication(QObject *parent = 0); 32 | ~MainApplication(); 33 | 34 | bool start(); 35 | void stop(); 36 | 37 | private: 38 | RaopService *raopService; 39 | DnssdService *dnssdService; 40 | AudioCallbacks m_callbacks; 41 | 42 | QSystemTrayIcon *trayIcon; 43 | QMenu *trayIconMenu; 44 | QAction *quitAction; 45 | 46 | signals: 47 | void quitRequested(); 48 | 49 | public slots: 50 | void aboutToQuit(); 51 | }; 52 | 53 | #endif // MAINAPPLICATION_H 54 | -------------------------------------------------------------------------------- /AirTV-Qt/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | MainWindow 3 | 4 | 5 | 6 | 0 7 | 0 8 | 400 9 | 300 10 | 11 | 12 | 13 | MainWindow 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/README.TXT: -------------------------------------------------------------------------------- 1 | Qt Solutions Component: Single Application 2 | 3 | The QtSingleApplication component provides support for 4 | applications that can be only started once per user. 5 | 6 | 7 | 8 | Version history: 9 | 10 | 2.0: - Version 1.3 ported to Qt 4. 11 | 12 | 2.1: - Fix compilation problem on Mac. 13 | 14 | 2.2: - Really fix the Mac compilation problem. 15 | - Mac: fix crash due to wrong object releasing. 16 | - Mac: Fix memory leak. 17 | 18 | 2.3: - Windows: Force creation of internal widget to make it work 19 | with Qt 4.2. 20 | 21 | 2.4: - Fix the system for automatic window raising on message 22 | reception. NOTE: minor API change. 23 | 24 | 2.5: - Mac: Fix isRunning() to work and report correctly. 25 | 26 | 2.6: - - initialize() is now obsolete, no longer necessary to call 27 | it 28 | - - Fixed race condition where multiple instances migth be started 29 | - - QtSingleCoreApplication variant provided for non-GUI (console) 30 | usage 31 | - Complete reimplementation. Visible changes: 32 | - LGPL release. 33 | 34 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/buildlib/buildlib.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=lib 2 | CONFIG += qt dll qtsingleapplication-buildlib 3 | mac:CONFIG += absolute_library_soname 4 | win32|mac:!wince*:!win32-msvc:!macx-xcode:CONFIG += debug_and_release build_all 5 | include(../src/qtsingleapplication.pri) 6 | TARGET = $$QTSINGLEAPPLICATION_LIBNAME 7 | DESTDIR = $$QTSINGLEAPPLICATION_LIBDIR 8 | win32 { 9 | DLLDESTDIR = $$[QT_INSTALL_BINS] 10 | QMAKE_DISTCLEAN += $$[QT_INSTALL_BINS]\\$${QTSINGLEAPPLICATION_LIBNAME}.dll 11 | } 12 | target.path = $$DESTDIR 13 | INSTALLS += target 14 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/common.pri: -------------------------------------------------------------------------------- 1 | infile(config.pri, SOLUTIONS_LIBRARY, yes): CONFIG += qtsingleapplication-uselib 2 | TEMPLATE += fakelib 3 | QTSINGLEAPPLICATION_LIBNAME = $$qtLibraryTarget(QtSolutions_SingleApplication-head) 4 | TEMPLATE -= fakelib 5 | QTSINGLEAPPLICATION_LIBDIR = $$PWD/lib 6 | unix:qtsingleapplication-uselib:!qtsingleapplication-buildlib:QMAKE_RPATHDIR += $$QTSINGLEAPPLICATION_LIBDIR 7 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "x$1" != "x" -a "x$1" != "x-library" ]; then 4 | echo "Usage: $0 [-library]" 5 | echo 6 | echo "-library: Build the component as a dynamic library (DLL). Default is to" 7 | echo " include the component source code directly in the application." 8 | echo 9 | exit 0 10 | fi 11 | 12 | rm -f config.pri 13 | if [ "x$1" = "x-library" ]; then 14 | echo "Configuring to build this component as a dynamic library." 15 | echo "SOLUTIONS_LIBRARY = yes" > config.pri 16 | fi 17 | 18 | echo 19 | echo "This component is now configured." 20 | echo 21 | echo "To build the component library (if requested) and example(s)," 22 | echo "run qmake and your make command." 23 | echo 24 | echo "To remove or reconfigure, run make distclean." 25 | echo 26 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/configure.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem 4 | rem "Main" 5 | rem 6 | 7 | if not "%1"=="" ( 8 | if not "%1"=="-library" ( 9 | call :PrintUsage 10 | goto EOF 11 | ) 12 | ) 13 | 14 | if exist config.pri. del config.pri 15 | if "%1"=="-library" ( 16 | echo Configuring to build this component as a dynamic library. 17 | echo SOLUTIONS_LIBRARY = yes > config.pri 18 | ) 19 | 20 | echo . 21 | echo This component is now configured. 22 | echo . 23 | echo To build the component library (if requested) and example(s), 24 | echo run qmake and your make or nmake command. 25 | echo . 26 | echo To remove or reconfigure, run make (nmake) distclean. 27 | echo . 28 | 29 | :PrintUsage 30 | echo Usage: configure.bat [-library] 31 | echo . 32 | echo -library: Build the component as a dynamic library (DLL). Default is to 33 | echo include the component source directly in the application. 34 | echo A DLL may be preferable for technical or licensing (LGPL) reasons. 35 | echo . 36 | goto EOF 37 | 38 | 39 | :EOF 40 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/classic.css: -------------------------------------------------------------------------------- 1 | BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { 2 | font-family: Arial, Geneva, Helvetica, sans-serif; 3 | } 4 | H1 { 5 | text-align: center; 6 | font-size: 160%; 7 | } 8 | H2 { 9 | font-size: 120%; 10 | } 11 | H3 { 12 | font-size: 100%; 13 | } 14 | 15 | h3.fn,span.fn 16 | { 17 | background-color: #eee; 18 | border-width: 1px; 19 | border-style: solid; 20 | border-color: #ddd; 21 | font-weight: bold; 22 | padding: 6px 0px 6px 10px; 23 | margin: 42px 0px 0px 0px; 24 | } 25 | 26 | hr { 27 | border: 0; 28 | color: #a0a0a0; 29 | background-color: #ccc; 30 | height: 1px; 31 | width: 100%; 32 | text-align: left; 33 | margin: 34px 0px 34px 0px; 34 | } 35 | 36 | table.valuelist { 37 | border-width: 1px 1px 1px 1px; 38 | border-style: solid; 39 | border-color: #dddddd; 40 | border-collapse: collapse; 41 | background-color: #f0f0f0; 42 | } 43 | 44 | table.indextable { 45 | border-width: 1px 1px 1px 1px; 46 | border-style: solid; 47 | border-collapse: collapse; 48 | background-color: #f0f0f0; 49 | border-color:#555; 50 | font-size: 100%; 51 | } 52 | 53 | table td.largeindex { 54 | border-width: 1px 1px 1px 1px; 55 | border-collapse: collapse; 56 | background-color: #f0f0f0; 57 | border-color:#555; 58 | font-size: 120%; 59 | } 60 | 61 | table.valuelist th { 62 | border-width: 1px 1px 1px 2px; 63 | padding: 4px; 64 | border-style: solid; 65 | border-color: #666; 66 | color:white; 67 | background-color:#666; 68 | } 69 | 70 | th.titleheader { 71 | border-width: 1px 0px 1px 0px; 72 | padding: 2px; 73 | border-style: solid; 74 | border-color: #666; 75 | color:white; 76 | background-color:#555; 77 | background-image:url('images/gradient.png')}; 78 | background-repeat: repeat-x; 79 | font-size: 100%; 80 | } 81 | 82 | 83 | th.largeheader { 84 | border-width: 1px 0px 1px 0px; 85 | padding: 4px; 86 | border-style: solid; 87 | border-color: #444; 88 | color:white; 89 | background-color:#555555; 90 | font-size: 120%; 91 | } 92 | 93 | p { 94 | 95 | margin-left: 4px; 96 | margin-top: 8px; 97 | margin-bottom: 8px; 98 | } 99 | 100 | a:link 101 | { 102 | color: #0046ad; 103 | text-decoration: none 104 | } 105 | 106 | a:visited 107 | { 108 | color: #672967; 109 | text-decoration: none 110 | } 111 | 112 | a.obsolete 113 | { 114 | color: #661100; 115 | text-decoration: none 116 | } 117 | 118 | a.compat 119 | { 120 | color: #661100; 121 | text-decoration: none 122 | } 123 | 124 | a.obsolete:visited 125 | { 126 | color: #995500; 127 | text-decoration: none 128 | } 129 | 130 | a.compat:visited 131 | { 132 | color: #995500; 133 | text-decoration: none 134 | } 135 | 136 | body 137 | { 138 | background: #ffffff; 139 | color: black 140 | } 141 | 142 | table.generic, table.annotated 143 | { 144 | border-width: 1px; 145 | border-color:#bbb; 146 | border-style:solid; 147 | border-collapse:collapse; 148 | } 149 | 150 | table td.memItemLeft { 151 | width: 180px; 152 | padding: 2px 0px 0px 8px; 153 | margin: 4px; 154 | border-width: 1px; 155 | border-color: #E0E0E0; 156 | border-style: none; 157 | font-size: 100%; 158 | white-space: nowrap 159 | } 160 | 161 | table td.memItemRight { 162 | padding: 2px 8px 0px 8px; 163 | margin: 4px; 164 | border-width: 1px; 165 | border-color: #E0E0E0; 166 | border-style: none; 167 | font-size: 100%; 168 | } 169 | 170 | table tr.odd { 171 | background: #f0f0f0; 172 | color: black; 173 | } 174 | 175 | table tr.even { 176 | background: #e4e4e4; 177 | color: black; 178 | } 179 | 180 | table.annotated th { 181 | padding: 3px; 182 | text-align: left 183 | } 184 | 185 | table.annotated td { 186 | padding: 3px; 187 | } 188 | 189 | table tr pre 190 | { 191 | padding-top: 0px; 192 | padding-bottom: 0px; 193 | padding-left: 0px; 194 | padding-right: 0px; 195 | border: none; 196 | background: none 197 | } 198 | 199 | tr.qt-style 200 | { 201 | background: #96E066; 202 | color: black 203 | } 204 | 205 | body pre 206 | { 207 | padding: 0.2em; 208 | border: #e7e7e7 1px solid; 209 | background: #f1f1f1; 210 | color: black 211 | } 212 | 213 | table tr.qt-code pre 214 | { 215 | padding: 0.2em; 216 | border: #e7e7e7 1px solid; 217 | background: #f1f1f1; 218 | color: black 219 | } 220 | 221 | span.preprocessor, span.preprocessor a 222 | { 223 | color: darkblue; 224 | } 225 | 226 | span.comment 227 | { 228 | color: darkred; 229 | font-style: italic 230 | } 231 | 232 | span.string,span.char 233 | { 234 | color: darkgreen; 235 | } 236 | 237 | .title 238 | { 239 | text-align: center 240 | } 241 | 242 | .subtitle 243 | { 244 | font-size: 0.8em 245 | } 246 | 247 | .small-subtitle 248 | { 249 | font-size: 0.65em 250 | } 251 | 252 | .qmlitem { 253 | padding: 0; 254 | } 255 | 256 | .qmlname { 257 | white-space: nowrap; 258 | } 259 | 260 | .qmltype { 261 | text-align: center; 262 | font-size: 160%; 263 | } 264 | 265 | .qmlproto { 266 | background-color: #eee; 267 | border-width: 1px; 268 | border-style: solid; 269 | border-color: #ddd; 270 | font-weight: bold; 271 | padding: 6px 10px 6px 10px; 272 | margin: 42px 0px 0px 0px; 273 | } 274 | 275 | .qmlreadonly { 276 | float: right; 277 | color: red 278 | } 279 | 280 | .qmldoc { 281 | } 282 | 283 | *.qmlitem p { 284 | } 285 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/shairplay/247bfa850917aa004d53d7ce540f6d68f8950bce/AirTV-Qt/qtsingleapplication/doc/html/images/qt-logo.png -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Single Application 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

Single Application
16 |

17 | 18 |

Description

19 |

The QtSingleApplication component provides support for applications that can be only started once per user.

20 |

For some applications it is useful or even critical that they are started only once by any user. Future attempts to start the application should activate any already running instance, and possibly perform requested actions, e.g. loading a file, in that instance.

21 |

The QtSingleApplication class provides an interface to detect a running instance, and to send command strings to that instance. For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui.

22 | 23 |

Classes

24 | 28 | 29 |

Examples

30 | 35 | 36 |

Tested platforms

37 |
    38 |
  • Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005
  • 39 |
  • Qt 4.4, 4.5 / Linux / gcc
  • 40 |
  • Qt 4.4, 4.5 / MacOS X 10.5 / gcc
  • 41 |
42 |


43 | 44 | 45 | 46 | 47 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
48 | 49 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication-obsolete.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | Obsolete Members for QtSingleApplication 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
  Home

Obsolete Members for QtSingleApplication

16 |

The following class members are obsolete. They are provided to keep old source code working. We strongly advise against using them in new code.

17 |

18 |

Public Functions

19 | 20 | 21 |
void initialize ( bool dummy = true )   (obsolete)
22 |
23 |

Member Function Documentation

24 |

void QtSingleApplication::initialize ( bool dummy = true )

25 |


26 | 27 | 28 | 29 | 30 |
Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)Trademarks
Qt Solutions
31 | 32 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication.dcf: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 | QtSingleApplication 6 | activateWindow 7 | activationWindow 8 | id 9 | isRunning 10 | messageReceived 11 | sendMessage 12 | setActivationWindow 13 |
14 |
15 |
16 |
17 | QtSingleCoreApplication 18 | id 19 | isRunning 20 | messageReceived 21 | sendMessage 22 |
23 |
24 |
25 |
26 |
27 | A non-GUI example 28 |
29 |
30 | A Trivial Example 31 |
32 |
33 | Loading Documents 34 |
35 |
36 | Single Application 37 |
38 |
39 |
40 | 41 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/html/qtsingleapplication.qhp: -------------------------------------------------------------------------------- 1 | 2 | 3 | com.nokia.qtsolutions.qtsingleapplication_head 4 | qdoc 5 | 6 | qt 7 | solutions 8 | qtsingleapplication 9 | 10 | 11 | qt 12 | solutions 13 | qtsingleapplication 14 | 15 |
16 |
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | qtsingleapplication.html 44 | index.html 45 | qtsingleapplication-example-trivial.html 46 | qtsinglecoreapplication.html 47 | qtsingleapplication-example-loader.html 48 | qtsinglecoreapplication-example-console.html 49 | classic.css 50 | images/qt-logo.png 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/images/qt-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/foxsen/shairplay/247bfa850917aa004d53d7ce540f6d68f8950bce/AirTV-Qt/qtsingleapplication/doc/images/qt-logo.png -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/doc/index.qdoc: -------------------------------------------------------------------------------- 1 | /*! 2 | \page index.html 3 | \title Single Application 4 | 5 | \section1 Description 6 | 7 | The QtSingleApplication component provides support 8 | for applications that can be only started once per user. 9 | 10 | 11 | 12 | For some applications it is useful or even critical that they are started 13 | only once by any user. Future attempts to start the application should 14 | activate any already running instance, and possibly perform requested 15 | actions, e.g. loading a file, in that instance. 16 | 17 | The QtSingleApplication class provides an interface to detect a running 18 | instance, and to send command strings to that instance. 19 | For console (non-GUI) applications, the QtSingleCoreApplication variant is provided, which avoids dependency on QtGui. 20 | 21 | 22 | 23 | 24 | \section1 Classes 25 | \list 26 | \i QtSingleApplication \i QtSingleCoreApplication\endlist 27 | 28 | \section1 Examples 29 | \list 30 | \i \link qtsingleapplication-example-trivial.html A Trivial Example \endlink \i \link qtsingleapplication-example-loader.html Loading Documents \endlink \i \link qtsinglecoreapplication-example-console.html A Non-GUI Example \endlink \endlist 31 | 32 | 33 | 34 | 35 | 36 | 37 | \section1 Tested platforms 38 | \list 39 | \i Qt 4.4, 4.5 / Windows XP / MSVC.NET 2005 40 | \i Qt 4.4, 4.5 / Linux / gcc 41 | \i Qt 4.4, 4.5 / MacOS X 10.5 / gcc 42 | \endlist 43 | 44 | 45 | 46 | 47 | */ -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/console.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | CONFIG += console 3 | SOURCES += main.cpp 4 | include(../../src/qtsinglecoreapplication.pri) 5 | QT -= gui 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/console.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsinglecoreapplication-example-console.html 41 | \title A non-GUI example 42 | 43 | This example shows how to use the single-application functionality 44 | in a console application. It does not require the \c QtGui library 45 | at all. 46 | 47 | The only differences from the GUI application usage demonstrated 48 | in the other examples are: 49 | 50 | 1) The \c.pro file should include \c qtsinglecoreapplication.pri 51 | instead of \c qtsingleapplication.pri 52 | 53 | 2) The class name is \c QtSingleCoreApplication instead of \c 54 | QtSingleApplication. 55 | 56 | 3) No calls are made regarding window activation, for obvious reasons. 57 | 58 | console.pro: 59 | \quotefile console/console.pro 60 | 61 | main.cpp: 62 | \quotefile console/main.cpp 63 | 64 | */ 65 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/console/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | 41 | #include "qtsinglecoreapplication.h" 42 | #include 43 | 44 | 45 | void report(const QString& msg) 46 | { 47 | qDebug("[%i] %s", (int)QCoreApplication::applicationPid(), qPrintable(msg)); 48 | } 49 | 50 | class MainClass : public QObject 51 | { 52 | Q_OBJECT 53 | public: 54 | MainClass() 55 | : QObject() 56 | {} 57 | 58 | public slots: 59 | void handleMessage(const QString& message) 60 | { 61 | report( "Message received: \"" + message + "\""); 62 | } 63 | }; 64 | 65 | int main(int argc, char **argv) 66 | { 67 | report("Starting up"); 68 | 69 | QtSingleCoreApplication app(argc, argv); 70 | 71 | if (app.isRunning()) { 72 | QString msg(QString("Hi master, I am %1.").arg(QCoreApplication::applicationPid())); 73 | bool sentok = app.sendMessage(msg, 2000); 74 | QString rep("Another instance is running, so I will exit."); 75 | rep += sentok ? " Message sent ok." : " Message sending failed; the other instance may be frozen."; 76 | report(rep); 77 | return 0; 78 | } else { 79 | report("No other instance is running; so I will."); 80 | MainClass mainObj; 81 | QObject::connect(&app, SIGNAL(messageReceived(const QString&)), 82 | &mainObj, SLOT(handleMessage(const QString&))); 83 | return app.exec(); 84 | } 85 | } 86 | 87 | 88 | #include "main.moc" 89 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/examples.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = subdirs 2 | SUBDIRS = trivial \ 3 | loader \ 4 | console 5 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/file1.qsl: -------------------------------------------------------------------------------- 1 | File 1 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/file2.qsl: -------------------------------------------------------------------------------- 1 | File 2 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/loader.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | include(../../src/qtsingleapplication.pri) 4 | 5 | SOURCES += main.cpp 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/loader.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsingleapplication-example-loader.html 41 | \title Loading Documents 42 | 43 | The application in this example loads or prints the documents 44 | passed as commandline parameters to further instances of this 45 | application. 46 | 47 | \quotefromfile loader/main.cpp 48 | \printuntil }; 49 | The user interface in this application is a QMainWindow subclass 50 | with a QMdiArea as the central widget. It implements a slot 51 | \c handleMessage() that will be connected to the messageReceived() 52 | signal of the QtSingleApplication class. 53 | 54 | \printuntil } 55 | The MainWindow constructor creates a minimal user interface. 56 | 57 | \printto case Print: 58 | The handleMessage() slot interprets the message passed in as a 59 | filename that can be prepended with \e /print to indicate that 60 | the file should just be printed rather than loaded. 61 | 62 | \printto #include 63 | Loading the file will also activate the window. 64 | 65 | \printto mw 66 | The \c main entry point function creates a QtSingleApplication 67 | object, and creates a message to send to a running instance 68 | of the application. If the message was sent successfully the 69 | process exits immediately. 70 | 71 | \printuntil } 72 | If the message could not be sent the application starts up. Note 73 | that \c false is passed to the call to setActivationWindow() to 74 | prevent automatic activation for every message received, e.g. when 75 | the application should just print a file. Instead, the message 76 | handling function determines whether activation is requested, and 77 | signals that by emitting the needToShow() signal. This is then 78 | simply connected directly to QtSingleApplication's 79 | activateWindow() slot. 80 | */ 81 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/loader/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | class MainWindow : public QMainWindow 50 | { 51 | Q_OBJECT 52 | public: 53 | MainWindow(); 54 | 55 | public slots: 56 | void handleMessage(const QString& message); 57 | 58 | signals: 59 | void needToShow(); 60 | 61 | private: 62 | QMdiArea *workspace; 63 | }; 64 | 65 | MainWindow::MainWindow() 66 | { 67 | workspace = new QMdiArea(this); 68 | 69 | setCentralWidget(workspace); 70 | } 71 | 72 | void MainWindow::handleMessage(const QString& message) 73 | { 74 | enum Action { 75 | Nothing, 76 | Open, 77 | Print 78 | } action; 79 | 80 | action = Nothing; 81 | QString filename = message; 82 | if (message.toLower().startsWith("/print ")) { 83 | filename = filename.mid(7); 84 | action = Print; 85 | } else if (!message.isEmpty()) { 86 | action = Open; 87 | } 88 | if (action == Nothing) { 89 | emit needToShow(); 90 | return; 91 | } 92 | 93 | QFile file(filename); 94 | QString contents; 95 | if (file.open(QIODevice::ReadOnly)) 96 | contents = file.readAll(); 97 | else 98 | contents = "[[Error: Could not load file " + filename + "]]"; 99 | 100 | QTextEdit *view = new QTextEdit; 101 | view->setPlainText(contents); 102 | 103 | switch(action) { 104 | case Print: 105 | { 106 | QPrinter printer; 107 | view->print(&printer); 108 | delete view; 109 | } 110 | break; 111 | 112 | case Open: 113 | { 114 | workspace->addSubWindow(view); 115 | view->setWindowTitle(message); 116 | view->show(); 117 | emit needToShow(); 118 | } 119 | break; 120 | default: 121 | break; 122 | }; 123 | } 124 | 125 | #include "main.moc" 126 | 127 | int main(int argc, char **argv) 128 | { 129 | QtSingleApplication instance("File loader QtSingleApplication example", argc, argv); 130 | QString message; 131 | for (int a = 1; a < argc; ++a) { 132 | message += argv[a]; 133 | if (a < argc-1) 134 | message += " "; 135 | } 136 | 137 | if (instance.sendMessage(message)) 138 | return 0; 139 | 140 | MainWindow mw; 141 | mw.handleMessage(message); 142 | mw.show(); 143 | 144 | QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), 145 | &mw, SLOT(handleMessage(const QString&))); 146 | 147 | instance.setActivationWindow(&mw, false); 148 | QObject::connect(&mw, SIGNAL(needToShow()), &instance, SLOT(activateWindow())); 149 | 150 | return instance.exec(); 151 | } 152 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/main.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | 43 | class TextEdit : public QTextEdit 44 | { 45 | Q_OBJECT 46 | public: 47 | TextEdit(QWidget *parent = 0) 48 | : QTextEdit(parent) 49 | {} 50 | public slots: 51 | void append(const QString &str) 52 | { 53 | QTextEdit::append(str); 54 | } 55 | }; 56 | 57 | #include "main.moc" 58 | 59 | 60 | 61 | int main(int argc, char **argv) 62 | { 63 | QtSingleApplication instance(argc, argv); 64 | if (instance.sendMessage("Wake up!")) 65 | return 0; 66 | 67 | TextEdit logview; 68 | logview.setReadOnly(true); 69 | logview.show(); 70 | 71 | instance.setActivationWindow(&logview); 72 | 73 | QObject::connect(&instance, SIGNAL(messageReceived(const QString&)), 74 | &logview, SLOT(append(const QString&))); 75 | 76 | return instance.exec(); 77 | } 78 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/trivial.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | 3 | include(../../src/qtsingleapplication.pri) 4 | 5 | SOURCES += main.cpp 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/examples/trivial/trivial.qdoc: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | /*! \page qtsingleapplication-example-trivial.html 41 | \title A Trivial Example 42 | 43 | The application in this example has a log-view that displays 44 | messages sent by further instances of the same application. 45 | 46 | The example demonstrates the use of the QtSingleApplication 47 | class to detect and communicate with a running instance of 48 | the application using the sendMessage() API. The messageReceived() 49 | signal is used to display received messages in a QTextEdit log. 50 | 51 | \quotefromfile trivial/main.cpp 52 | \printuntil instance 53 | The example has only the \c main entry point function. 54 | A QtSingleApplication object is created immediately. 55 | 56 | \printuntil return 57 | If another instance of this application is already running, 58 | sendMessage() will succeed, and this instance just exits 59 | immediately. 60 | 61 | \printuntil show() 62 | Otherwise the instance continues as normal and creates the 63 | user interface. 64 | 65 | \printuntil return instance.exec(); 66 | The \c logview object is also set as the application's activation 67 | window. Every time a message is received, the window will be raised 68 | and activated automatically. 69 | 70 | The messageReceived() signal is also connected to the QTextEdit's 71 | append() slot. Every message received from further instances of 72 | this application will be displayed in the log. 73 | 74 | Finally the event loop is entered. 75 | */ 76 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/qtsingleapplication.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE=subdirs 2 | CONFIG += ordered 3 | include(common.pri) 4 | qtsingleapplication-uselib:SUBDIRS=buildlib 5 | SUBDIRS+=examples 6 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/QtLockedFile: -------------------------------------------------------------------------------- 1 | #include "qtlockedfile.h" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/QtSingleApplication: -------------------------------------------------------------------------------- 1 | #include "qtsingleapplication.h" 2 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlocalpeer.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTLOCALPEER_H 41 | #define QTLOCALPEER_H 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | #include "qtlockedfile.h" 48 | 49 | class QtLocalPeer : public QObject 50 | { 51 | Q_OBJECT 52 | 53 | public: 54 | QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); 55 | bool isClient(); 56 | bool sendMessage(const QString &message, int timeout); 57 | QString applicationId() const 58 | { return id; } 59 | 60 | Q_SIGNALS: 61 | void messageReceived(const QString &message); 62 | 63 | protected Q_SLOTS: 64 | void receiveConnection(); 65 | 66 | protected: 67 | QString id; 68 | QString socketName; 69 | QLocalServer* server; 70 | QtLP_Private::QtLockedFile lockFile; 71 | 72 | private: 73 | static const char* ack; 74 | }; 75 | 76 | #endif // QTLOCALPEER_H 77 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlockedfile.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTLOCKEDFILE_H 41 | #define QTLOCKEDFILE_H 42 | 43 | #include 44 | #ifdef Q_OS_WIN 45 | #include 46 | #endif 47 | 48 | #if defined(Q_WS_WIN) 49 | # if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT) 50 | # define QT_QTLOCKEDFILE_EXPORT 51 | # elif defined(QT_QTLOCKEDFILE_IMPORT) 52 | # if defined(QT_QTLOCKEDFILE_EXPORT) 53 | # undef QT_QTLOCKEDFILE_EXPORT 54 | # endif 55 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport) 56 | # elif defined(QT_QTLOCKEDFILE_EXPORT) 57 | # undef QT_QTLOCKEDFILE_EXPORT 58 | # define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport) 59 | # endif 60 | #else 61 | # define QT_QTLOCKEDFILE_EXPORT 62 | #endif 63 | 64 | namespace QtLP_Private { 65 | 66 | class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile 67 | { 68 | public: 69 | enum LockMode { NoLock = 0, ReadLock, WriteLock }; 70 | 71 | QtLockedFile(); 72 | QtLockedFile(const QString &name); 73 | ~QtLockedFile(); 74 | 75 | bool open(OpenMode mode); 76 | 77 | bool lock(LockMode mode, bool block = true); 78 | bool unlock(); 79 | bool isLocked() const; 80 | LockMode lockMode() const; 81 | 82 | private: 83 | #ifdef Q_OS_WIN 84 | Qt::HANDLE wmutex; 85 | Qt::HANDLE rmutex; 86 | QVector rmutexes; 87 | QString mutexname; 88 | 89 | Qt::HANDLE getMutexHandle(int idx, bool doCreate); 90 | bool waitMutex(Qt::HANDLE mutex, bool doBlock); 91 | 92 | #endif 93 | LockMode m_lock_mode; 94 | }; 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtlockedfile_unix.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include "qtlockedfile.h" 46 | 47 | bool QtLockedFile::lock(LockMode mode, bool block) 48 | { 49 | if (!isOpen()) { 50 | qWarning("QtLockedFile::lock(): file is not opened"); 51 | return false; 52 | } 53 | 54 | if (mode == NoLock) 55 | return unlock(); 56 | 57 | if (mode == m_lock_mode) 58 | return true; 59 | 60 | if (m_lock_mode != NoLock) 61 | unlock(); 62 | 63 | struct flock fl; 64 | fl.l_whence = SEEK_SET; 65 | fl.l_start = 0; 66 | fl.l_len = 0; 67 | fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK; 68 | int cmd = block ? F_SETLKW : F_SETLK; 69 | int ret = fcntl(handle(), cmd, &fl); 70 | 71 | if (ret == -1) { 72 | if (errno != EINTR && errno != EAGAIN) 73 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 74 | return false; 75 | } 76 | 77 | 78 | m_lock_mode = mode; 79 | return true; 80 | } 81 | 82 | 83 | bool QtLockedFile::unlock() 84 | { 85 | if (!isOpen()) { 86 | qWarning("QtLockedFile::unlock(): file is not opened"); 87 | return false; 88 | } 89 | 90 | if (!isLocked()) 91 | return true; 92 | 93 | struct flock fl; 94 | fl.l_whence = SEEK_SET; 95 | fl.l_start = 0; 96 | fl.l_len = 0; 97 | fl.l_type = F_UNLCK; 98 | int ret = fcntl(handle(), F_SETLKW, &fl); 99 | 100 | if (ret == -1) { 101 | qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno)); 102 | return false; 103 | } 104 | 105 | m_lock_mode = NoLock; 106 | return true; 107 | } 108 | 109 | QtLockedFile::~QtLockedFile() 110 | { 111 | if (isOpen()) 112 | unlock(); 113 | } 114 | 115 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsingleapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTSINGLEAPPLICATION_H 41 | #define QTSINGLEAPPLICATION_H 42 | 43 | #include 44 | 45 | class QtLocalPeer; 46 | 47 | #if defined(Q_WS_WIN) 48 | # if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT) 49 | # define QT_QTSINGLEAPPLICATION_EXPORT 50 | # elif defined(QT_QTSINGLEAPPLICATION_IMPORT) 51 | # if defined(QT_QTSINGLEAPPLICATION_EXPORT) 52 | # undef QT_QTSINGLEAPPLICATION_EXPORT 53 | # endif 54 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport) 55 | # elif defined(QT_QTSINGLEAPPLICATION_EXPORT) 56 | # undef QT_QTSINGLEAPPLICATION_EXPORT 57 | # define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport) 58 | # endif 59 | #else 60 | # define QT_QTSINGLEAPPLICATION_EXPORT 61 | #endif 62 | 63 | class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication 64 | { 65 | Q_OBJECT 66 | 67 | public: 68 | QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); 69 | QtSingleApplication(const QString &id, int &argc, char **argv); 70 | QtSingleApplication(int &argc, char **argv, Type type); 71 | #if defined(Q_WS_X11) 72 | QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 73 | QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0); 74 | QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0); 75 | #endif 76 | 77 | bool isRunning(); 78 | QString id() const; 79 | 80 | void setActivationWindow(QWidget* aw, bool activateOnMessage = true); 81 | QWidget* activationWindow() const; 82 | 83 | // Obsolete: 84 | void initialize(bool dummy = true) 85 | { isRunning(); Q_UNUSED(dummy) } 86 | 87 | public Q_SLOTS: 88 | bool sendMessage(const QString &message, int timeout = 5000); 89 | void activateWindow(); 90 | 91 | 92 | Q_SIGNALS: 93 | void messageReceived(const QString &message); 94 | 95 | 96 | private: 97 | void sysInit(const QString &appId = QString()); 98 | QtLocalPeer *peer; 99 | QWidget *actWin; 100 | }; 101 | 102 | #endif // QTSINGLEAPPLICATION_H 103 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsingleapplication.pri: -------------------------------------------------------------------------------- 1 | include(../common.pri) 2 | INCLUDEPATH += $$PWD 3 | DEPENDPATH += $$PWD 4 | QT *= network 5 | 6 | qtsingleapplication-uselib:!qtsingleapplication-buildlib { 7 | LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME 8 | } else { 9 | SOURCES += $$PWD/qtsingleapplication.cpp $$PWD/qtlocalpeer.cpp 10 | HEADERS += $$PWD/qtsingleapplication.h $$PWD/qtlocalpeer.h 11 | } 12 | 13 | win32 { 14 | contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT 15 | else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT 16 | } 17 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsinglecoreapplication.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** 3 | ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 4 | ** All rights reserved. 5 | ** 6 | ** Contact: Nokia Corporation (qt-info@nokia.com) 7 | ** 8 | ** This file is part of a Qt Solutions component. 9 | ** 10 | ** You may use this file under the terms of the BSD license as follows: 11 | ** 12 | ** "Redistribution and use in source and binary forms, with or without 13 | ** modification, are permitted provided that the following conditions are 14 | ** met: 15 | ** * Redistributions of source code must retain the above copyright 16 | ** notice, this list of conditions and the following disclaimer. 17 | ** * Redistributions in binary form must reproduce the above copyright 18 | ** notice, this list of conditions and the following disclaimer in 19 | ** the documentation and/or other materials provided with the 20 | ** distribution. 21 | ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 22 | ** the names of its contributors may be used to endorse or promote 23 | ** products derived from this software without specific prior written 24 | ** permission. 25 | ** 26 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 27 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 28 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 29 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 30 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 33 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 34 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 35 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 36 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 37 | ** 38 | ****************************************************************************/ 39 | 40 | #ifndef QTSINGLECOREAPPLICATION_H 41 | #define QTSINGLECOREAPPLICATION_H 42 | 43 | #include 44 | 45 | class QtLocalPeer; 46 | 47 | class QtSingleCoreApplication : public QCoreApplication 48 | { 49 | Q_OBJECT 50 | 51 | public: 52 | QtSingleCoreApplication(int &argc, char **argv); 53 | QtSingleCoreApplication(const QString &id, int &argc, char **argv); 54 | 55 | bool isRunning(); 56 | QString id() const; 57 | 58 | public Q_SLOTS: 59 | bool sendMessage(const QString &message, int timeout = 5000); 60 | 61 | 62 | Q_SIGNALS: 63 | void messageReceived(const QString &message); 64 | 65 | 66 | private: 67 | QtLocalPeer* peer; 68 | }; 69 | 70 | #endif // QTSINGLECOREAPPLICATION_H 71 | -------------------------------------------------------------------------------- /AirTV-Qt/qtsingleapplication/src/qtsinglecoreapplication.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | DEPENDPATH += $$PWD 3 | HEADERS += $$PWD/qtsinglecoreapplication.h $$PWD/qtlocalpeer.h 4 | SOURCES += $$PWD/qtsinglecoreapplication.cpp $$PWD/qtlocalpeer.cpp 5 | 6 | QT *= network 7 | 8 | win32:contains(TEMPLATE, lib):contains(CONFIG, shared) { 9 | DEFINES += QT_QTSINGLECOREAPPLICATION_EXPORT=__declspec(dllexport) 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Following licenses apply: 2 | 3 | src/lib/alac/* - MIT License 4 | src/lib/crypto/* - New BSD License 5 | src/lib/http_parser.* - MIT License 6 | src/lib/* - LGPLv2.1+ License 7 | src/bindings/* - MIT License 8 | src/* - MIT License 9 | AirTV-Qt/* - LGPLv2.1+ License 10 | 11 | Also the following files are used, although not necessary: 12 | 13 | AirTV-Qt/qtsingleapplication/src/* - New BSD License 14 | 15 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = include src 2 | 3 | ACLOCAL_AMFLAGS = -I m4 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Shairplay 2 | ========= 3 | Free portable AirPlay server implementation similar to [ShairPort](https://github.com/abrasive/shairport). 4 | 5 | Currently only AirPort Express emulation is supported. 6 | Update by foxsen, 2015/11/25: 7 | * small fixes for AAC-ELD/ipv6 handling etc. Thanks to HaoLi for pointing them out. (untested) 8 | * I have figured out the different handling of iso9 and will update the code when having more time. 9 | * I am also learned most of the necessary information for the video mirroring part, but don't have enough time and interest to implement all the details and maintain them. If some guys would like to implement a fully open source shairplay that can handle both audio and video, I would like to help. Instead of the protocol implementation, I am interested more on the fairplay part and will try to get the hidden private key at spare time. I think I am close to that. 10 | 11 | Update by foxsen, 2015/4/20: 12 | Experimental support for fairplay protocol and airplay: 13 | * fairplay encrypted audio is supported (et == 3) 14 | * AAC-ELD audio is supported 15 | * airplay service framework is added, up to the point that the mirroring 16 | connection starts streaming. But the UI and callbacks need to be done. 17 | * fairplay support is performed via interactions with a server 18 | 19 | Disclaimer 20 | ---------- 21 | All the resources in this repository are written using only freely available 22 | information from the internet. The code and related resources are meant for 23 | educational purposes only. It is the responsibility of the user to make sure 24 | all local laws are adhered to. 25 | 26 | Installation 27 | ------------ 28 | 29 | First you need to install some dependencies, for example on Ubuntu you would 30 | write: 31 | ``` 32 | sudo apt-get install autoconf automake libtool 33 | sudo apt-get install libltdl-dev libao-dev libavahi-compat-libdnssd-dev \ 34 | libplist-dev libfdk-aac-dev libssl-dev 35 | sudo apt-get install avahi-daemon 36 | ``` 37 | 38 | Note: The Raspbian apt repositories do not have [libplist](https://github.com/Chronic-Dev/libplist) or [libfdk-aac](https://github.com/mstorsjo/fdk-aac). You will need to compile these from source. 39 | 40 | ``` 41 | ./autogen.sh 42 | ./configure 43 | make 44 | sudo make install 45 | ``` 46 | 47 | Notice that libao is required in order to install the shairplay binary, 48 | otherwise only the library is compiled and installed. 49 | 50 | Usage 51 | ----- 52 | 53 | Check available options with ```shairplay --help```: 54 | 55 | ``` 56 | Usage: shairplay [OPTION...] 57 | 58 | -a, --apname=AirPort Sets Airport name 59 | -p, --password=secret Sets password 60 | -o, --server_port=5000 Sets port for RAOP service 61 | --ao_driver=driver Sets the ao driver (optional) 62 | --ao_devicename=devicename Sets the ao device name (optional) 63 | --ao_deviceid=id Sets the ao device id (optional) 64 | --enable_airplay Start airplay service 65 | -h, --help This help 66 | ``` 67 | 68 | Start the server with ```shairplay```, if you are connected to a Wi-Fi the 69 | server should show as an AirPort Express on your iOS devices and Mac OS X 70 | computers in the same network. 71 | 72 | Notice that you need to have the airport.key file in your working directory when 73 | starting the shairplay service. It is not included in the binary for possible 74 | legal reasons. 75 | 76 | Related software 77 | ---------------- 78 | 79 | * [ShairPort](https://github.com/abrasive/shairport), original AirPort Express emulator 80 | * [ALAC](http://craz.net/programs/itunes/alac.html), ALAC decoder by David Hammerton 81 | 82 | Description 83 | ----------- 84 | 85 | Short description about what each file in the main library does: 86 | 87 | ``` 88 | src/lib/base64.* - base64 encoder/decoder 89 | src/lib/dnssd.* - dnssd helper functions 90 | src/lib/http_parser.* - HTTP parser from joyent (nginx fork) 91 | src/lib/http_request.* - Request parser that uses http_parser 92 | src/lib/http_response.* - Extremely simple HTTP response serializer 93 | src/lib/httpd.* - Generic HTTP/RTSP server 94 | src/lib/logger.* - Logging related functions 95 | src/lib/netutils.* - Mostly socket related code 96 | src/lib/raop.* - Main RAOP handler, handles all RTSP stuff 97 | src/lib/raop_rtp.* - Handles the RAOP RTP related stuff (UDP/TCP) 98 | src/lib/raop_buffer.* - Parses and buffers RAOP packets, resend logic here 99 | src/lib/rsakey.* - Decrypts and parses the RSA key to bigints 100 | src/lib/rsapem.* - Converts the RSA PEM key to DER encoded bytes 101 | src/lib/sdp.* - Extremely simple RAOP specific SDP parser 102 | src/lib/utils.* - Utils for reading a file and handling strings 103 | ``` 104 | 105 | Short description about what each file in the Qt application does: 106 | 107 | ``` 108 | AirTV-Qt/main.cpp - Initializes the application 109 | AirTV-Qt/mainapplication.cpp - Creates the tray icon and starts RAOP 110 | AirTV-Qt/raopservice.cpp - Handles all communication with the library 111 | AirTV-Qt/raopcallbackhandler.cpp - Converts C callbacks to Qt callbacks 112 | AirTV-Qt/audiooutput.cpp - Takes care of the actual audio output 113 | ``` 114 | 115 | -------------------------------------------------------------------------------- /airport.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpQIBAAKCAQEA59dE8qLieItsH1WgjrcFRKj6eUWqi+bGLOX1HL3U3GhC/j0Qg90u3sG/1CUt 3 | wC5vOYvfDmFI6oSFXi5ELabWJmT2dKHzBJKa3k9ok+8t9ucRqMd6DZHJ2YCCLlDRKSKv6kDqnw4U 4 | wPdpOMXziC/AMj3Z/lUVX1G7WSHCAWKf1zNS1eLvqr+boEjXuBOitnZ/bDzPHrTOZz0Dew0uowxf 5 | /+sG+NCK3eQJVxqcaJ/vEHKIVd2M+5qL71yJQ+87X6oV3eaYvt3zWZYD6z5vYTcrtij2VZ9Zmni/ 6 | UAaHqn9JdsBWLUEpVviYnhimNVvYFZeCXg/IdTQ+x4IRdiXNv5hEewIDAQABAoIBAQDl8Axy9XfW 7 | BLmkzkEiqoSwF0PsmVrPzH9KsnwLGH+QZlvjWd8SWYGN7u1507HvhF5N3drJoVU3O14nDY4TFQAa 8 | LlJ9VM35AApXaLyY1ERrN7u9ALKd2LUwYhM7Km539O4yUFYikE2nIPscEsA5ltpxOgUGCY7b7ez5 9 | NtD6nL1ZKauw7aNXmVAvmJTcuPxWmoktF3gDJKK2wxZuNGcJE0uFQEG4Z3BrWP7yoNuSK3dii2jm 10 | lpPHr0O/KnPQtzI3eguhe0TwUem/eYSdyzMyVx/YpwkzwtYL3sR5k0o9rKQLtvLzfAqdBxBurciz 11 | aaA/L0HIgAmOit1GJA2saMxTVPNhAoGBAPfgv1oeZxgxmotiCcMXFEQEWflzhWYTsXrhUIuz5jFu 12 | a39GLS99ZEErhLdrwj8rDDViRVJ5skOp9zFvlYAHs0xh92ji1E7V/ysnKBfsMrPkk5KSKPrnjndM 13 | oPdevWnVkgJ5jxFuNgxkOLMuG9i53B4yMvDTCRiIPMQ++N2iLDaRAoGBAO9v//mU8eVkQaoANf0Z 14 | oMjW8CN4xwWA2cSEIHkd9AfFkftuv8oyLDCG3ZAf0vrhrrtkrfa7ef+AUb69DNggq4mHQAYBp7L+ 15 | k5DKzJrKuO0r+R0YbY9pZD1+/g9dVt91d6LQNepUE/yY2PP5CNoFmjedpLHMOPFdVgqDzDFxU8hL 16 | AoGBANDrr7xAJbqBjHVwIzQ4To9pb4BNeqDndk5Qe7fT3+/H1njGaC0/rXE0Qb7q5ySgnsCb3DvA 17 | cJyRM9SJ7OKlGt0FMSdJD5KG0XPIpAVNwgpXXH5MDJg09KHeh0kXo+QA6viFBi21y340NonnEfdf 18 | 54PX4ZGS/Xac1UK+pLkBB+zRAoGAf0AY3H3qKS2lMEI4bzEFoHeK3G895pDaK3TFBVmD7fV0Zhov 19 | 17fegFPMwOII8MisYm9ZfT2Z0s5Ro3s5rkt+nvLAdfC/PYPKzTLalpGSwomSNYJcB9HNMlmhkGzc 20 | 1JnLYT4iyUyx6pcZBmCd8bD0iwY/FzcgNDaUmbX9+XDvRA0CgYEAkE7pIPlE71qvfJQgoA9em0gI 21 | LAuE4Pu13aKiJnfft7hIjbK+5kyb3TysZvoyDnb3HOKvInK7vXbKuU4ISgxB2bB3HcYzQMGsz1qJ 22 | 2gG0N5hvJpzwwhbhXqFKA4zaaSrw622wDniAK5MlIE0tIAKKP4yxNGjoD2QYjhBGuhvkWKY= 23 | -----END RSA PRIVATE KEY----- 24 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf -vif 4 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ(2.61) 5 | AC_INIT([shairplay], [0.9.0], [juhovh@iki.fi]) 6 | AC_CONFIG_MACRO_DIR([m4]) 7 | AC_CONFIG_SRCDIR([src/shairplay.c]) 8 | AC_CONFIG_HEADER([config.h]) 9 | AM_INIT_AUTOMAKE([foreign]) 10 | 11 | # Checks for programs. 12 | AC_PROG_CC 13 | AC_LIBTOOL_WIN32_DLL 14 | AC_PROG_LIBTOOL 15 | 16 | # Checks for libraries. 17 | LT_LIB_DLLOAD 18 | LT_LIB_M 19 | 20 | # Checks for header files. 21 | AC_HEADER_STDC 22 | 23 | # Checks for typedefs, structures, and compiler characteristics. 24 | 25 | # Checks for library functions. 26 | AC_CHECK_LIB([socket],[connect]) 27 | AC_CHECK_LIB([pthread],[pthread_create]) 28 | 29 | 30 | # Custom check for os, similar to webkit 31 | AC_MSG_CHECKING([for native Win32]) 32 | case "$host" in 33 | *-*-mingw*) 34 | os_win32=yes 35 | ;; 36 | *) 37 | os_win32=no 38 | ;; 39 | esac 40 | AC_MSG_RESULT([$os_win32]) 41 | 42 | case "$host" in 43 | *-*-linux*) 44 | os_linux=yes 45 | ;; 46 | *-*-freebsd*) 47 | os_freebsd=yes 48 | ;; 49 | *-*-darwin*) 50 | os_darwin=yes 51 | ;; 52 | esac 53 | 54 | case "$host_os" in 55 | gnu* | linux* | k*bsd*-gnu) 56 | os_gnu=yes 57 | ;; 58 | *) 59 | os_gnu=no 60 | ;; 61 | esac 62 | 63 | # OS conditionals 64 | AM_CONDITIONAL([OS_WIN32],[test "$os_win32" = "yes"]) 65 | AM_CONDITIONAL([OS_UNIX],[test "$os_win32" = "no"]) 66 | AM_CONDITIONAL([OS_LINUX],[test "$os_linux" = "yes"]) 67 | AM_CONDITIONAL([OS_GNU],[test "$os_gnu" = "yes"]) 68 | AM_CONDITIONAL([OS_FREEBSD],[test "$os_freebsd" = "yes"]) 69 | 70 | # Custom check for libao 71 | PKG_CHECK_MODULES([libao], [ao >= 1.1.0], [have_libao=1], [have_libao=0]) 72 | AM_CONDITIONAL([HAVE_LIBAO], [test "$have_libao" -eq 1]) 73 | 74 | 75 | 76 | AC_CONFIG_FILES( 77 | [Makefile] 78 | [include/Makefile] 79 | [src/Makefile] 80 | [src/lib/Makefile] 81 | [src/lib/alac/Makefile] 82 | [src/lib/aac_eld/Makefile] 83 | [src/lib/crypto/Makefile] 84 | ) 85 | AC_OUTPUT 86 | -------------------------------------------------------------------------------- /include/Makefile.am: -------------------------------------------------------------------------------- 1 | nobase_include_HEADERS = shairplay/dnssd.h shairplay/raop.h 2 | -------------------------------------------------------------------------------- /include/shairplay/airplay.h: -------------------------------------------------------------------------------- 1 | #ifndef AIRPLAY_H 2 | #define AIRPLAY_H 3 | 4 | #if defined (WIN32) && defined(DLL_EXPORT) 5 | # define AIRPLAY_API __declspec(dllexport) 6 | #else 7 | # define AIRPLAY_API 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /* Define syslog style log levels */ 16 | #define AIRPLAY_LOG_EMERG 0 /* system is unusable */ 17 | #define AIRPLAY_LOG_ALERT 1 /* action must be taken immediately */ 18 | #define AIRPLAY_LOG_CRIT 2 /* critical conditions */ 19 | #define AIRPLAY_LOG_ERR 3 /* error conditions */ 20 | #define AIRPLAY_LOG_WARNING 4 /* warning conditions */ 21 | #define AIRPLAY_LOG_NOTICE 5 /* normal but significant condition */ 22 | #define AIRPLAY_LOG_INFO 6 /* informational */ 23 | #define AIRPLAY_LOG_DEBUG 7 /* debug-level messages */ 24 | 25 | 26 | typedef struct airplay_s airplay_t; 27 | 28 | typedef void (*airplay_log_callback_t)(void *cls, int level, const char *msg); 29 | 30 | struct airplay_callbacks_s { 31 | void* cls; 32 | 33 | /* Compulsory callback functions */ 34 | void* (*audio_init)(void *cls, int bits, int channels, int samplerate); 35 | void (*audio_process)(void *cls, void *session, const void *buffer, int buflen); 36 | void (*audio_destroy)(void *cls, void *session); 37 | 38 | /* Optional but recommended callback functions */ 39 | void (*audio_flush)(void *cls, void *session); 40 | void (*audio_set_volume)(void *cls, void *session, float volume); 41 | void (*audio_set_metadata)(void *cls, void *session, const void *buffer, int buflen); 42 | void (*audio_set_coverart)(void *cls, void *session, const void *buffer, int buflen); 43 | }; 44 | typedef struct airplay_callbacks_s airplay_callbacks_t; 45 | 46 | AIRPLAY_API airplay_t *airplay_init(int max_clients, airplay_callbacks_t *callbacks, const char *pemkey, int *error); 47 | AIRPLAY_API airplay_t *airplay_init_from_keyfile(int max_clients, airplay_callbacks_t *callbacks, const char *keyfile, int *error); 48 | 49 | AIRPLAY_API void airplay_set_log_level(airplay_t *airplay, int level); 50 | AIRPLAY_API void airplay_set_log_callback(airplay_t *airplay, airplay_log_callback_t callback, void *cls); 51 | 52 | AIRPLAY_API int airplay_start(airplay_t *airplay, unsigned short *port, const char *hwaddr, int hwaddrlen, const char *password); 53 | AIRPLAY_API int airplay_is_running(airplay_t *airplay); 54 | AIRPLAY_API void airplay_stop(airplay_t *airplay); 55 | 56 | AIRPLAY_API void airplay_destroy(airplay_t *airplay); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | #endif 62 | -------------------------------------------------------------------------------- /include/shairplay/dnssd.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSSD_H 2 | #define DNSSD_H 3 | 4 | #if defined(WIN32) && defined(DLL_EXPORT) 5 | # define DNSSD_API __declspec(dllexport) 6 | #else 7 | # define DNSSD_API 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define DNSSD_ERROR_NOERROR 0 15 | #define DNSSD_ERROR_HWADDRLEN 1 16 | #define DNSSD_ERROR_OUTOFMEM 2 17 | #define DNSSD_ERROR_LIBNOTFOUND 3 18 | #define DNSSD_ERROR_PROCNOTFOUND 4 19 | 20 | typedef struct dnssd_s dnssd_t; 21 | 22 | DNSSD_API dnssd_t *dnssd_init(int *error); 23 | 24 | DNSSD_API int dnssd_register_raop(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen, int password); 25 | DNSSD_API int dnssd_register_airplay(dnssd_t *dnssd, const char *name, unsigned short port, const char *hwaddr, int hwaddrlen); 26 | 27 | DNSSD_API void dnssd_unregister_raop(dnssd_t *dnssd); 28 | DNSSD_API void dnssd_unregister_airplay(dnssd_t *dnssd); 29 | 30 | DNSSD_API void dnssd_destroy(dnssd_t *dnssd); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | #endif 36 | -------------------------------------------------------------------------------- /include/shairplay/raop.h: -------------------------------------------------------------------------------- 1 | #ifndef RAOP_H 2 | #define RAOP_H 3 | 4 | #if defined (WIN32) && defined(DLL_EXPORT) 5 | # define RAOP_API __declspec(dllexport) 6 | #else 7 | # define RAOP_API 8 | #endif 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | 15 | /* Define syslog style log levels */ 16 | #define RAOP_LOG_EMERG 0 /* system is unusable */ 17 | #define RAOP_LOG_ALERT 1 /* action must be taken immediately */ 18 | #define RAOP_LOG_CRIT 2 /* critical conditions */ 19 | #define RAOP_LOG_ERR 3 /* error conditions */ 20 | #define RAOP_LOG_WARNING 4 /* warning conditions */ 21 | #define RAOP_LOG_NOTICE 5 /* normal but significant condition */ 22 | #define RAOP_LOG_INFO 6 /* informational */ 23 | #define RAOP_LOG_DEBUG 7 /* debug-level messages */ 24 | 25 | 26 | typedef struct raop_s raop_t; 27 | 28 | typedef void (*raop_log_callback_t)(void *cls, int level, const char *msg); 29 | 30 | struct raop_callbacks_s { 31 | void* cls; 32 | 33 | /* Compulsory callback functions */ 34 | void* (*audio_init)(void *cls, int bits, int channels, int samplerate); 35 | void (*audio_process)(void *cls, void *session, const void *buffer, int buflen); 36 | void (*audio_destroy)(void *cls, void *session); 37 | 38 | /* Optional but recommended callback functions */ 39 | void (*audio_flush)(void *cls, void *session); 40 | void (*audio_set_volume)(void *cls, void *session, float volume); 41 | void (*audio_set_metadata)(void *cls, void *session, const void *buffer, int buflen); 42 | void (*audio_set_coverart)(void *cls, void *session, const void *buffer, int buflen); 43 | }; 44 | typedef struct raop_callbacks_s raop_callbacks_t; 45 | 46 | RAOP_API raop_t *raop_init(int max_clients, raop_callbacks_t *callbacks, const char *pemkey, int *error); 47 | RAOP_API raop_t *raop_init_from_keyfile(int max_clients, raop_callbacks_t *callbacks, const char *keyfile, int *error); 48 | 49 | RAOP_API void raop_set_log_level(raop_t *raop, int level); 50 | RAOP_API void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls); 51 | 52 | RAOP_API int raop_start(raop_t *raop, unsigned short *port, const char *hwaddr, int hwaddrlen, const char *password); 53 | RAOP_API int raop_is_running(raop_t *raop); 54 | RAOP_API void raop_stop(raop_t *raop); 55 | 56 | RAOP_API void raop_destroy(raop_t *raop); 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif 61 | #endif 62 | -------------------------------------------------------------------------------- /m4/pkg.m4: -------------------------------------------------------------------------------- 1 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- 2 | # 3 | # Copyright © 2004 Scott James Remnant . 4 | # 5 | # This program is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, but 11 | # WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | # General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | # 19 | # As a special exception to the GNU General Public License, if you 20 | # distribute this file as part of a program that contains a 21 | # configuration script generated by Autoconf, you may include it under 22 | # the same distribution terms that you use for the rest of that program. 23 | 24 | # PKG_PROG_PKG_CONFIG([MIN-VERSION]) 25 | # ---------------------------------- 26 | AC_DEFUN([PKG_PROG_PKG_CONFIG], 27 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) 28 | m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) 29 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl 30 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then 31 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) 32 | fi 33 | if test -n "$PKG_CONFIG"; then 34 | _pkg_min_version=m4_default([$1], [0.9.0]) 35 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) 36 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then 37 | AC_MSG_RESULT([yes]) 38 | else 39 | AC_MSG_RESULT([no]) 40 | PKG_CONFIG="" 41 | fi 42 | 43 | fi[]dnl 44 | ])# PKG_PROG_PKG_CONFIG 45 | 46 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 47 | # 48 | # Check to see whether a particular set of modules exists. Similar 49 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. 50 | # 51 | # 52 | # Similar to PKG_CHECK_MODULES, make sure that the first instance of 53 | # this or PKG_CHECK_MODULES is called, or make sure to call 54 | # PKG_CHECK_EXISTS manually 55 | # -------------------------------------------------------------- 56 | AC_DEFUN([PKG_CHECK_EXISTS], 57 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 58 | if test -n "$PKG_CONFIG" && \ 59 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then 60 | m4_ifval([$2], [$2], [:]) 61 | m4_ifvaln([$3], [else 62 | $3])dnl 63 | fi]) 64 | 65 | 66 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) 67 | # --------------------------------------------- 68 | m4_define([_PKG_CONFIG], 69 | [if test -n "$$1"; then 70 | pkg_cv_[]$1="$$1" 71 | elif test -n "$PKG_CONFIG"; then 72 | PKG_CHECK_EXISTS([$3], 73 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], 74 | [pkg_failed=yes]) 75 | else 76 | pkg_failed=untried 77 | fi[]dnl 78 | ])# _PKG_CONFIG 79 | 80 | # _PKG_SHORT_ERRORS_SUPPORTED 81 | # ----------------------------- 82 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], 83 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 84 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then 85 | _pkg_short_errors_supported=yes 86 | else 87 | _pkg_short_errors_supported=no 88 | fi[]dnl 89 | ])# _PKG_SHORT_ERRORS_SUPPORTED 90 | 91 | 92 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], 93 | # [ACTION-IF-NOT-FOUND]) 94 | # 95 | # 96 | # Note that if there is a possibility the first call to 97 | # PKG_CHECK_MODULES might not happen, you should be sure to include an 98 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac 99 | # 100 | # 101 | # -------------------------------------------------------------- 102 | AC_DEFUN([PKG_CHECK_MODULES], 103 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 104 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl 105 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl 106 | 107 | pkg_failed=no 108 | AC_MSG_CHECKING([for $1]) 109 | 110 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) 111 | _PKG_CONFIG([$1][_LIBS], [libs], [$2]) 112 | 113 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS 114 | and $1[]_LIBS to avoid the need to call pkg-config. 115 | See the pkg-config man page for more details.]) 116 | 117 | if test $pkg_failed = yes; then 118 | _PKG_SHORT_ERRORS_SUPPORTED 119 | if test $_pkg_short_errors_supported = yes; then 120 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1` 121 | else 122 | $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1` 123 | fi 124 | # Put the nasty error message in config.log where it belongs 125 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD 126 | 127 | ifelse([$4], , [AC_MSG_ERROR(dnl 128 | [Package requirements ($2) were not met: 129 | 130 | $$1_PKG_ERRORS 131 | 132 | Consider adjusting the PKG_CONFIG_PATH environment variable if you 133 | installed software in a non-standard prefix. 134 | 135 | _PKG_TEXT 136 | ])], 137 | [AC_MSG_RESULT([no]) 138 | $4]) 139 | elif test $pkg_failed = untried; then 140 | ifelse([$4], , [AC_MSG_FAILURE(dnl 141 | [The pkg-config script could not be found or is too old. Make sure it 142 | is in your PATH or set the PKG_CONFIG environment variable to the full 143 | path to pkg-config. 144 | 145 | _PKG_TEXT 146 | 147 | To get pkg-config, see .])], 148 | [$4]) 149 | else 150 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS 151 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS 152 | AC_MSG_RESULT([yes]) 153 | ifelse([$3], , :, [$3]) 154 | fi[]dnl 155 | ])# PKG_CHECK_MODULES 156 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = lib 2 | 3 | AM_CPPFLAGS = -I$(top_srcdir)/include 4 | 5 | if HAVE_LIBAO 6 | bin_PROGRAMS = shairplay 7 | shairplay_SOURCES = shairplay.c audio.h audio.c 8 | shairplay_LDADD = lib/libshairplay.la 9 | shairplay_CFLAGS = 10 | shairplay_LDFLAGS = -static-libtool-libs 11 | 12 | shairplay_CFLAGS += $(libao_CFLAGS) 13 | shairplay_LDADD += $(libao_LIBS) 14 | endif 15 | 16 | -------------------------------------------------------------------------------- /src/audio.h: -------------------------------------------------------------------------------- 1 | #ifndef __SHAIRPLAY_AUDIO_H__ 2 | #define __SHAIRPLAY_AUDIO_H__ 3 | 4 | #include 5 | 6 | int audio_prepare(char *driver, char *devicename, char *deviceid, raop_callbacks_t *raop_cbs); 7 | void audio_shutdown(); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/bindings/qt4/dnssdservice.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "dnssdservice.h" 25 | 26 | DnssdService::DnssdService(QObject *parent) : 27 | QObject(parent) 28 | { 29 | } 30 | 31 | bool DnssdService::init() 32 | { 33 | int error; 34 | m_dnssd = dnssd_init(&error); 35 | if (!m_dnssd) { 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | DnssdService::~DnssdService() 42 | { 43 | dnssd_destroy(m_dnssd); 44 | } 45 | 46 | void DnssdService::registerRaop(const QString & name, quint16 port, const QByteArray & hwaddr) 47 | { 48 | dnssd_register_raop(m_dnssd, name.toUtf8().data(), port, hwaddr.data(), hwaddr.size(), 0); 49 | } 50 | 51 | void DnssdService::unregisterRaop() 52 | { 53 | dnssd_unregister_raop(m_dnssd); 54 | } 55 | 56 | void DnssdService::registerAirplay(const QString &name, quint16 port, const QByteArray &hwaddr) 57 | { 58 | dnssd_register_airplay(m_dnssd, name.toUtf8().data(), port, hwaddr.data(), hwaddr.size()); 59 | } 60 | 61 | void DnssdService::unregisterAirplay() 62 | { 63 | dnssd_unregister_airplay(m_dnssd); 64 | } 65 | -------------------------------------------------------------------------------- /src/bindings/qt4/dnssdservice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef DNSSDSERVICE_H 25 | #define DNSSDSERVICE_H 26 | 27 | #include 28 | 29 | #include 30 | 31 | class DnssdService : public QObject 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit DnssdService(QObject *parent = 0); 36 | ~DnssdService(); 37 | 38 | bool init(); 39 | 40 | void registerRaop(const QString & name, quint16 port, const QByteArray & hwaddr); 41 | void unregisterRaop(); 42 | 43 | void registerAirplay(const QString & name, quint16 port, const QByteArray & hwaddr); 44 | void unregisterAirplay(); 45 | 46 | private: 47 | dnssd_t * m_dnssd; 48 | 49 | signals: 50 | 51 | public slots: 52 | 53 | }; 54 | 55 | #endif // DNSSDSERVICE_H 56 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbackhandler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "raopcallbackhandler.h" 25 | 26 | RaopCallbackHandler::RaopCallbackHandler(QObject *parent) : 27 | QObject(parent) 28 | { 29 | } 30 | 31 | void RaopCallbackHandler::init(RaopAudioHandler *callbacks) 32 | { 33 | m_callbacks = callbacks; 34 | } 35 | 36 | void RaopCallbackHandler::audioInit(void *session, int bits, int channels, int samplerate) 37 | { 38 | void **retval = (void**)session; 39 | if (m_callbacks) { 40 | *retval = m_callbacks->audioInit(bits, channels, samplerate); 41 | } 42 | } 43 | 44 | void RaopCallbackHandler::audioProcess(void *session, void *buffer, int buflen) 45 | { 46 | if (m_callbacks) { 47 | m_callbacks->audioProcess(session, QByteArray((const char *)buffer, buflen)); 48 | } 49 | } 50 | 51 | void RaopCallbackHandler::audioDestroy(void *session) 52 | { 53 | if (m_callbacks) { 54 | m_callbacks->audioDestroy(session); 55 | } 56 | } 57 | 58 | void RaopCallbackHandler::audioFlush(void *session) 59 | { 60 | if (m_callbacks) { 61 | m_callbacks->audioFlush(session); 62 | } 63 | } 64 | 65 | void RaopCallbackHandler::audioSetVolume(void *session, float volume) 66 | { 67 | if (m_callbacks) { 68 | m_callbacks->audioSetVolume(session, volume); 69 | } 70 | } 71 | 72 | void RaopCallbackHandler::audioSetMetadata(void *session, void *buffer, int buflen) 73 | { 74 | if (m_callbacks) { 75 | m_callbacks->audioSetMetadata(session, QByteArray((const char *)buffer, buflen)); 76 | } 77 | } 78 | 79 | void RaopCallbackHandler::audioSetCoverart(void *session, void *buffer, int buflen) 80 | { 81 | if (m_callbacks) { 82 | m_callbacks->audioSetCoverart(session, QByteArray((const char *)buffer, buflen)); 83 | } 84 | } 85 | 86 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbackhandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPCALLBACKHANDLER_H 25 | #define RAOPCALLBACKHANDLER_H 26 | 27 | #include 28 | 29 | #include "raopcallbacks.h" 30 | 31 | class RaopCallbackHandler : public QObject 32 | { 33 | Q_OBJECT 34 | public: 35 | explicit RaopCallbackHandler(QObject *parent = 0); 36 | void init(RaopAudioHandler *callbacks); 37 | 38 | private: 39 | RaopAudioHandler * m_callbacks; 40 | 41 | signals: 42 | 43 | public slots: 44 | void audioInit(void *session, int bits, int channels, int samplerate); 45 | void audioProcess(void *session, void *buffer, int buflen); 46 | void audioDestroy(void *session); 47 | void audioFlush(void *session); 48 | void audioSetVolume(void *session, float volume); 49 | void audioSetMetadata(void *session, void *buffer, int buflen); 50 | void audioSetCoverart(void *session, void *buffer, int buflen); 51 | }; 52 | 53 | #endif // RAOPCALLBACKHANDLER_H 54 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopcallbacks.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPCALLBACKS_H 25 | #define RAOPCALLBACKS_H 26 | 27 | #include 28 | 29 | class RaopLogHandler : public QObject 30 | { 31 | Q_OBJECT 32 | public: 33 | explicit RaopLogHandler(QObject *parent = 0) : QObject(parent) {} 34 | 35 | virtual void logCallback(int level, const char *msg) = 0; 36 | }; 37 | 38 | class RaopAudioHandler : public QObject 39 | { 40 | Q_OBJECT 41 | public: 42 | explicit RaopAudioHandler(QObject *parent = 0) : QObject(parent) {} 43 | 44 | virtual void *audioInit(int bits, int channels, int samplerate) = 0; 45 | virtual void audioProcess(void *session, const QByteArray & buffer) = 0; 46 | virtual void audioDestroy(void *session) = 0; 47 | 48 | virtual void audioFlush(void *session) { Q_UNUSED(session) } 49 | virtual void audioSetVolume(void *session, float volume) { Q_UNUSED(session) Q_UNUSED(volume) } 50 | virtual void audioSetMetadata(void *session, const QByteArray & buffer) { Q_UNUSED(session) Q_UNUSED(buffer) } 51 | virtual void audioSetCoverart(void *session, const QByteArray & buffer) { Q_UNUSED(session) Q_UNUSED(buffer) } 52 | }; 53 | 54 | #endif // RAOPCALLBACKS_H 55 | -------------------------------------------------------------------------------- /src/bindings/qt4/raopservice.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2012 Juho Vähä-Herttua 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included 13 | * in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef RAOPSERVICE_H 25 | #define RAOPSERVICE_H 26 | 27 | #include 28 | 29 | #include 30 | 31 | #include "raopcallbacks.h" 32 | 33 | class RaopService : public QObject 34 | { 35 | Q_OBJECT 36 | public: 37 | explicit RaopService(QObject *parent = 0); 38 | ~RaopService(); 39 | 40 | bool init(int max_clients, RaopAudioHandler *callbacks); 41 | void setLogLevel(int level); 42 | void setLogHandler(RaopLogHandler *logger); 43 | bool start(quint16 port, const QByteArray & hwaddr); 44 | bool isRunning(); 45 | void stop(); 46 | 47 | private: 48 | raop_t * m_raop; 49 | 50 | signals: 51 | 52 | public slots: 53 | 54 | }; 55 | 56 | #endif // RAOPSERVICE_H 57 | -------------------------------------------------------------------------------- /src/lib/Makefile.am: -------------------------------------------------------------------------------- 1 | SUBDIRS = crypto alac aac_eld 2 | 3 | AM_CPPFLAGS = -I$(top_srcdir)/include/shairplay 4 | 5 | lib_LTLIBRARIES = libshairplay.la 6 | libshairplay_la_SOURCES = base64.c base64.h digest.c digest.h dnssd.c dnssdint.h http_parser.c http_parser.h http_request.c http_request.h http_response.c http_response.h httpd.c httpd.h logger.c logger.h netutils.c netutils.h raop.c raop_buffer.c raop_buffer.h raop_rtp.c raop_rtp.h rsakey.c rsakey.h rsapem.c rsapem.h sdp.c sdp.h utils.c utils.h compat.h memalign.h sockets.h threads.h airplay.c fairplay.h fairplay.c 7 | libshairplay_la_CPPFLAGS = $(AM_CPPFLAGS) 8 | 9 | # This library depends on 3rd party libraries 10 | libshairplay_la_LIBADD = crypto/libcrypto.la alac/libalac.la aac_eld/libaac_eld.la 11 | libshairplay_la_LDFLAGS = -no-undefined -version-info 0:0:0 12 | 13 | ### Update -version-info above with the following rules 14 | # 1. Start with version information of ‘0:0:0’ for each libtool library. 15 | # 2. Update the version information only immediately before a public release of 16 | # your software. More frequent updates are unnecessary, and only guarantee 17 | # that the current interface number gets larger faster. 18 | # 3. If the library source code has changed at all since the last update, then 19 | # increment revision (‘c:r:a’ becomes ‘c:r+1:a’). 20 | # 4. If any interfaces have been added, removed, or changed since the last 21 | # update, increment current, and set revision to 0. 22 | # 5. If any interfaces have been added since the last public release, then 23 | # increment age. 24 | # 6. If any interfaces have been removed or changed since the last public 25 | # release, then set age to 0. 26 | ### 27 | 28 | libshairplay_la_LIBADD += $(LIBADD_DLOPEN) 29 | libshairplay_la_LIBADD += $(LIBM) 30 | libshairplay_la_LIBADD += -lfdk-aac 31 | libshairplay_la_LIBADD += -lplist 32 | 33 | if OS_WIN32 34 | libshairplay_la_CPPFLAGS += -DDLL_EXPORT 35 | libshairplay_la_LDFLAGS += -lws2_32 -lwinmm 36 | else 37 | libshairplay_la_LDFLAGS += -export-symbols-regex '^(raop|dnssd)' 38 | endif 39 | -------------------------------------------------------------------------------- /src/lib/aac_eld/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libaac_eld.la 2 | libaac_eld_la_SOURCES = aac_eld.c aac_eld.h 3 | -------------------------------------------------------------------------------- /src/lib/aac_eld/aac_eld.c: -------------------------------------------------------------------------------- 1 | /* 2 | * decode AAC-ELD audio data from mac by XBMC, and play it by SDL 3 | * 4 | * modify: 5 | * 2012-10-31 first version (ffmpeg tutorial03.c) 6 | * 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include "aac_eld.h" 13 | 14 | /* ---------------------------------------------------------- */ 15 | /* next n lines is libfdk-aac config */ 16 | /* ---------------------------------------------------------- */ 17 | 18 | /* period size 480 samples */ 19 | #define N_SAMPLE 480 20 | /* ASC config binary data */ 21 | unsigned char eld_conf[] = { 0xF8, 0xE8, 0x50, 0x00 }; 22 | unsigned char *conf[] = { eld_conf }; //TODO just for aac eld config 23 | static unsigned int conf_len = sizeof(eld_conf); 24 | 25 | static int pcm_pkt_size = 4 * N_SAMPLE; 26 | 27 | struct aac_eld_file { 28 | int fdk_flags; 29 | HANDLE_AACDECODER phandle; 30 | TRANSPORT_TYPE transportFmt; 31 | unsigned int nrOfLayers; 32 | CStreamInfo *stream_info; 33 | }; 34 | 35 | /* 36 | * create aac eld decoder 37 | */ 38 | aac_eld_file *create_aac_eld(void) 39 | { 40 | int ret = 0; 41 | aac_eld_file *aac; 42 | 43 | aac = malloc(sizeof(aac_eld_file)); 44 | if (!aac) return NULL; 45 | 46 | aac->fdk_flags = 0; 47 | aac->transportFmt = 0; //raw 48 | aac->nrOfLayers = 1; // 1 layer 49 | aac->phandle = aacDecoder_Open(aac->transportFmt, aac->nrOfLayers); 50 | if (aac->phandle == NULL) { 51 | printf("aacDecoder open faild!\n"); 52 | return NULL; 53 | } 54 | 55 | printf("conf_len = %d\n", conf_len); 56 | ret = aacDecoder_ConfigRaw(aac->phandle, conf, &conf_len); 57 | if (ret != AAC_DEC_OK) { 58 | fprintf(stderr, "Unable to set configRaw\n"); 59 | return NULL; 60 | } 61 | 62 | aac->stream_info = aacDecoder_GetStreamInfo(aac->phandle); 63 | if (aac->stream_info == NULL) { 64 | printf("aacDecoder_GetStreamInfo failed!\n"); 65 | return NULL; 66 | } 67 | printf("> stream info: channel = %d\tsample_rate = %d\tframe_size = %d\taot = %d\tbitrate = %d\n", \ 68 | aac->stream_info->channelConfig, aac->stream_info->aacSampleRate, 69 | aac->stream_info->aacSamplesPerFrame, aac->stream_info->aot, aac->stream_info->bitRate); 70 | return aac; 71 | } 72 | 73 | void destroy_aac_eld(aac_eld_file *aac) 74 | { 75 | if (aac) { 76 | aacDecoder_Close(aac->phandle); 77 | free(aac); 78 | } 79 | } 80 | 81 | void aac_eld_set_info(aac_eld_file *aac_eld, char *inputbuffer) 82 | { 83 | } 84 | 85 | /* 86 | * called by external, aac data input queue 87 | */ 88 | void aac_eld_decode_frame(aac_eld_file *aac_eld, unsigned char *inbuffer, int inputsize, void *outbuffer, int *outputsize) 89 | { 90 | int ret = 0; 91 | unsigned char *input_buf[1]; 92 | int sizes[1]; 93 | int valid_size; 94 | 95 | input_buf[0] = inbuffer; 96 | sizes[0] = inputsize; 97 | 98 | /* step 1 -> fill aac_data_buf to decoder's internal buf */ 99 | ret = aacDecoder_Fill(aac_eld->phandle, input_buf, sizes, &valid_size); 100 | if (ret != AAC_DEC_OK) { 101 | fprintf(stderr, "Fill failed: %x\n", ret); 102 | *outputsize = 0; 103 | return; 104 | } 105 | 106 | /* step 2 -> call decoder function */ 107 | ret = aacDecoder_DecodeFrame(aac_eld->phandle, outbuffer, pcm_pkt_size, aac_eld->fdk_flags); 108 | if (ret != AAC_DEC_OK) { 109 | fprintf(stderr, "aacDecoder_DecodeFrame : 0x%x\n", ret); 110 | *outputsize = 0; 111 | return; 112 | } 113 | 114 | *outputsize = pcm_pkt_size; 115 | 116 | /* TOCHECK: need to check and handle inputsize != valid_size ? */ 117 | fprintf(stderr, "pcm output %d\n", *outputsize); 118 | } 119 | 120 | -------------------------------------------------------------------------------- /src/lib/aac_eld/aac_eld.h: -------------------------------------------------------------------------------- 1 | #ifndef __AAC__ELD_DECOMP_H 2 | #define __AAC__ELD_DECOMP_H 3 | 4 | typedef struct aac_eld_file aac_eld_file; 5 | 6 | aac_eld_file *create_aac_eld(); 7 | void aac_eld_decode_frame(aac_eld_file *aac_eld, 8 | unsigned char *inbuffer, int inputsize, 9 | void *outbuffer, int *outputsize); 10 | void aac_eld_set_info(aac_eld_file *aac_eld, char *inputbuffer); 11 | void destroy_aac_eld(aac_eld_file *aac_eld); 12 | 13 | #endif /* __ALAC__DECOMP_H */ 14 | 15 | -------------------------------------------------------------------------------- /src/lib/alac/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libalac.la 2 | libalac_la_SOURCES = alac.c alac.h stdint_win.h 3 | -------------------------------------------------------------------------------- /src/lib/alac/alac.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALAC__DECOMP_H 2 | #define __ALAC__DECOMP_H 3 | 4 | typedef struct alac_file alac_file; 5 | 6 | alac_file *create_alac(int samplesize, int numchannels); 7 | void alac_decode_frame(alac_file *alac, 8 | unsigned char *inbuffer, 9 | void *outbuffer, int *outputsize); 10 | void alac_set_info(alac_file *alac, char *inputbuffer); 11 | void destroy_alac(alac_file *alac); 12 | 13 | #endif /* __ALAC__DECOMP_H */ 14 | 15 | -------------------------------------------------------------------------------- /src/lib/alac/stdint_win.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef ALAC_STDINT_WIN_H__ 3 | #define ALAC_STDINT_WIN_H__ 4 | 5 | typedef signed char int8_t; 6 | typedef signed short int16_t; 7 | typedef signed int int32_t; 8 | typedef signed __int64 int64_t; 9 | typedef unsigned char uint8_t; 10 | typedef unsigned short uint16_t; 11 | typedef unsigned int uint32_t; 12 | typedef unsigned __int64 uint64_t; 13 | 14 | #endif // ALAC_STDINT_WIN_H__ -------------------------------------------------------------------------------- /src/lib/base64.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef BASE64_H 16 | #define BASE64_H 17 | 18 | typedef struct base64_s base64_t; 19 | 20 | base64_t *base64_init(const char *charlist, int use_padding, int skip_spaces); 21 | 22 | int base64_encoded_length(base64_t *base64, int srclen); 23 | 24 | int base64_encode(base64_t *base64, char *dst, const unsigned char *src, int srclen); 25 | int base64_decode(base64_t *base64, unsigned char **dst, const char *src, int srclen); 26 | 27 | void base64_destroy(base64_t *base64); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/lib/compat.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef COMPAT_H 16 | #define COMPAT_H 17 | 18 | #if defined(WIN32) 19 | #include 20 | #include 21 | #ifndef snprintf 22 | #define snprintf _snprintf 23 | #endif 24 | #else 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #endif 36 | 37 | #include "memalign.h" 38 | #include "sockets.h" 39 | #include "threads.h" 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/lib/crypto/Makefile.am: -------------------------------------------------------------------------------- 1 | noinst_LTLIBRARIES = libcrypto.la 2 | libcrypto_la_SOURCES = bigint.c bigint.h bigint_impl.h aes.c hmac.c md5.c rc4.c sha1.c crypto.h os_port.h config.h new_aes.c aes_locl.h 3 | 4 | -------------------------------------------------------------------------------- /src/lib/crypto/aes_locl.h: -------------------------------------------------------------------------------- 1 | /* crypto/aes/aes.h -*- mode:C; c-file-style: "eay" -*- */ 2 | /* ==================================================================== 3 | * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in 14 | * the documentation and/or other materials provided with the 15 | * distribution. 16 | * 17 | * 3. All advertising materials mentioning features or use of this 18 | * software must display the following acknowledgment: 19 | * "This product includes software developed by the OpenSSL Project 20 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21 | * 22 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 | * endorse or promote products derived from this software without 24 | * prior written permission. For written permission, please contact 25 | * openssl-core@openssl.org. 26 | * 27 | * 5. Products derived from this software may not be called "OpenSSL" 28 | * nor may "OpenSSL" appear in their names without prior written 29 | * permission of the OpenSSL Project. 30 | * 31 | * 6. Redistributions of any form whatsoever must retain the following 32 | * acknowledgment: 33 | * "This product includes software developed by the OpenSSL Project 34 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35 | * 36 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 | * OF THE POSSIBILITY OF SUCH DAMAGE. 48 | * ==================================================================== 49 | * 50 | */ 51 | 52 | #ifndef HEADER_AES_LOCL_H 53 | #define HEADER_AES_LOCL_H 54 | 55 | #include 56 | 57 | #ifdef OPENSSL_NO_AES 58 | #error AES is disabled. 59 | #endif 60 | 61 | #include 62 | #include 63 | #include 64 | 65 | #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64)) 66 | # define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) 67 | # define GETU32(p) SWAP(*((u32 *)(p))) 68 | # define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } 69 | #else 70 | # define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) 71 | # define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } 72 | #endif 73 | 74 | #ifdef AES_LONG 75 | typedef unsigned long u32; 76 | #else 77 | typedef unsigned int u32; 78 | #endif 79 | typedef unsigned short u16; 80 | typedef unsigned char u8; 81 | 82 | #define MAXKC (256/32) 83 | #define MAXKB (256/8) 84 | #define MAXNR 14 85 | 86 | /* This controls loop-unrolling in aes_core.c */ 87 | #undef FULL_UNROLL 88 | 89 | #endif /* !HEADER_AES_LOCL_H */ 90 | -------------------------------------------------------------------------------- /src/lib/crypto/bigint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | #ifndef BIGINT_HEADER 32 | #define BIGINT_HEADER 33 | 34 | #include "crypto.h" 35 | 36 | BI_CTX *bi_initialize(void); 37 | void bi_terminate(BI_CTX *ctx); 38 | void bi_permanent(bigint *bi); 39 | void bi_depermanent(bigint *bi); 40 | void bi_clear_cache(BI_CTX *ctx); 41 | void bi_free(BI_CTX *ctx, bigint *bi); 42 | bigint *bi_copy(bigint *bi); 43 | bigint *bi_clone(BI_CTX *ctx, const bigint *bi); 44 | void bi_export(BI_CTX *ctx, bigint *bi, uint8_t *data, int size); 45 | bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int len); 46 | bigint *int_to_bi(BI_CTX *ctx, comp i); 47 | 48 | /* the functions that actually do something interesting */ 49 | bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); 50 | bigint *bi_subtract(BI_CTX *ctx, bigint *bia, 51 | bigint *bib, int *is_negative); 52 | bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); 53 | bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); 54 | bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); 55 | bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); 56 | int bi_compare(bigint *bia, bigint *bib); 57 | void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); 58 | void bi_free_mod(BI_CTX *ctx, int mod_offset); 59 | 60 | #ifdef CONFIG_SSL_FULL_MODE 61 | void bi_print(const char *label, bigint *bi); 62 | bigint *bi_str_import(BI_CTX *ctx, const char *data); 63 | #endif 64 | 65 | /** 66 | * @def bi_mod 67 | * Find the residue of B. bi_set_mod() must be called before hand. 68 | */ 69 | #define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) 70 | 71 | /** 72 | * bi_residue() is technically the same as bi_mod(), but it uses the 73 | * appropriate reduction technique (which is bi_mod() when doing classical 74 | * reduction). 75 | */ 76 | #if defined(CONFIG_BIGINT_MONTGOMERY) 77 | #define bi_residue(A, B) bi_mont(A, B) 78 | bigint *bi_mont(BI_CTX *ctx, bigint *bixy); 79 | #elif defined(CONFIG_BIGINT_BARRETT) 80 | #define bi_residue(A, B) bi_barrett(A, B) 81 | bigint *bi_barrett(BI_CTX *ctx, bigint *bi); 82 | #else /* if defined(CONFIG_BIGINT_CLASSICAL) */ 83 | #define bi_residue(A, B) bi_mod(A, B) 84 | #endif 85 | 86 | #ifdef CONFIG_BIGINT_SQUARE 87 | bigint *bi_square(BI_CTX *ctx, bigint *bi); 88 | #else 89 | #define bi_square(A, B) bi_multiply(A, bi_copy(B), B) 90 | #endif 91 | 92 | #ifdef CONFIG_BIGINT_CRT 93 | bigint *bi_crt(BI_CTX *ctx, bigint *bi, 94 | bigint *dP, bigint *dQ, 95 | bigint *p, bigint *q, 96 | bigint *qInv); 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /src/lib/crypto/config.h: -------------------------------------------------------------------------------- 1 | 2 | #define CONFIG_BIGINT_BARRETT 1 3 | #define CONFIG_BIGINT_CRT 1 4 | #define CONFIG_BIGINT_SQUARE 1 5 | #define CONFIG_BIGINT_32BIT 1 6 | 7 | -------------------------------------------------------------------------------- /src/lib/crypto/hmac.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /** 32 | * HMAC implementation - This code was originally taken from RFC2104 33 | * See http://www.ietf.org/rfc/rfc2104.txt and 34 | * http://www.faqs.org/rfcs/rfc2202.html 35 | */ 36 | 37 | #include 38 | #include "os_port.h" 39 | #include "crypto.h" 40 | 41 | /** 42 | * Perform HMAC-MD5 43 | * NOTE: does not handle keys larger than the block size. 44 | */ 45 | void hmac_md5(const uint8_t *msg, int length, const uint8_t *key, 46 | int key_len, uint8_t *digest) 47 | { 48 | MD5_CTX context; 49 | uint8_t k_ipad[64]; 50 | uint8_t k_opad[64]; 51 | int i; 52 | 53 | memset(k_ipad, 0, sizeof k_ipad); 54 | memset(k_opad, 0, sizeof k_opad); 55 | memcpy(k_ipad, key, key_len); 56 | memcpy(k_opad, key, key_len); 57 | 58 | for (i = 0; i < 64; i++) 59 | { 60 | k_ipad[i] ^= 0x36; 61 | k_opad[i] ^= 0x5c; 62 | } 63 | 64 | MD5_Init(&context); 65 | MD5_Update(&context, k_ipad, 64); 66 | MD5_Update(&context, msg, length); 67 | MD5_Final(digest, &context); 68 | MD5_Init(&context); 69 | MD5_Update(&context, k_opad, 64); 70 | MD5_Update(&context, digest, MD5_SIZE); 71 | MD5_Final(digest, &context); 72 | } 73 | 74 | /** 75 | * Perform HMAC-SHA1 76 | * NOTE: does not handle keys larger than the block size. 77 | */ 78 | void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key, 79 | int key_len, uint8_t *digest) 80 | { 81 | SHA1_CTX context; 82 | uint8_t k_ipad[64]; 83 | uint8_t k_opad[64]; 84 | int i; 85 | 86 | memset(k_ipad, 0, sizeof k_ipad); 87 | memset(k_opad, 0, sizeof k_opad); 88 | memcpy(k_ipad, key, key_len); 89 | memcpy(k_opad, key, key_len); 90 | 91 | for (i = 0; i < 64; i++) 92 | { 93 | k_ipad[i] ^= 0x36; 94 | k_opad[i] ^= 0x5c; 95 | } 96 | 97 | SHA1_Init(&context); 98 | SHA1_Update(&context, k_ipad, 64); 99 | SHA1_Update(&context, msg, length); 100 | SHA1_Final(digest, &context); 101 | SHA1_Init(&context); 102 | SHA1_Update(&context, k_opad, 64); 103 | SHA1_Update(&context, digest, SHA1_SIZE); 104 | SHA1_Final(digest, &context); 105 | } 106 | -------------------------------------------------------------------------------- /src/lib/crypto/os_port.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /** 32 | * @file os_port.h 33 | * 34 | * Some stuff to minimise the differences between windows and linux/unix 35 | */ 36 | 37 | #ifndef HEADER_OS_PORT_H 38 | #define HEADER_OS_PORT_H 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | #include 45 | 46 | #if defined(WIN32) 47 | #define STDCALL /* Would be __stdcall but we don't want it */ 48 | #define EXP_FUNC __declspec(dllexport) 49 | #else 50 | #define STDCALL 51 | #define EXP_FUNC 52 | #endif 53 | 54 | #if defined(_WIN32_WCE) 55 | #undef WIN32 56 | #define WIN32 57 | #endif 58 | 59 | #ifdef WIN32 60 | 61 | /* Windows CE stuff */ 62 | #if defined(_WIN32_WCE) 63 | #include 64 | #define abort() exit(1) 65 | #else 66 | #include 67 | #include 68 | #include 69 | #include 70 | #endif /* _WIN32_WCE */ 71 | 72 | #include 73 | #include 74 | #undef getpid 75 | #undef open 76 | #undef close 77 | #undef sleep 78 | #undef gettimeofday 79 | #undef dup2 80 | #undef unlink 81 | 82 | #define SOCKET_READ(A,B,C) recv(A,B,C,0) 83 | #define SOCKET_WRITE(A,B,C) send(A,B,C,0) 84 | #define SOCKET_CLOSE(A) closesocket(A) 85 | #define srandom(A) srand(A) 86 | #define random() rand() 87 | #define getpid() _getpid() 88 | #define snprintf _snprintf 89 | #define open(A,B) _open(A,B) 90 | #define dup2(A,B) _dup2(A,B) 91 | #define unlink(A) _unlink(A) 92 | #define close(A) _close(A) 93 | #define read(A,B,C) _read(A,B,C) 94 | #define write(A,B,C) _write(A,B,C) 95 | #define sleep(A) Sleep(A*1000) 96 | #define usleep(A) Sleep(A/1000) 97 | #define strdup(A) _strdup(A) 98 | #define chroot(A) _chdir(A) 99 | #define chdir(A) _chdir(A) 100 | #ifndef lseek 101 | #define lseek(A,B,C) _lseek(A,B,C) 102 | #endif 103 | 104 | /* This fix gets around a problem where a win32 application on a cygwin xterm 105 | doesn't display regular output (until a certain buffer limit) - but it works 106 | fine under a normal DOS window. This is a hack to get around the issue - 107 | see http://www.khngai.com/emacs/tty.php */ 108 | #define TTY_FLUSH() if (!_isatty(_fileno(stdout))) fflush(stdout); 109 | 110 | 111 | typedef UINT8 uint8_t; 112 | typedef INT8 int8_t; 113 | typedef UINT16 uint16_t; 114 | typedef INT16 int16_t; 115 | typedef UINT32 uint32_t; 116 | typedef INT32 int32_t; 117 | typedef UINT64 uint64_t; 118 | typedef INT64 int64_t; 119 | typedef int socklen_t; 120 | 121 | #else /* Not Win32 */ 122 | 123 | #ifdef __sun__ 124 | #include 125 | #else 126 | #include 127 | #endif /* Not Solaris */ 128 | 129 | #include 130 | #include 131 | #include 132 | #include 133 | #include 134 | #include 135 | #include 136 | #include 137 | #include 138 | #include 139 | #include 140 | #include 141 | 142 | #define SOCKET_READ(A,B,C) read(A,B,C) 143 | #define SOCKET_WRITE(A,B,C) write(A,B,C) 144 | #define SOCKET_CLOSE(A) if (A >= 0) close(A) 145 | #define TTY_FLUSH() 146 | 147 | #endif /* Not Win32 */ 148 | 149 | /* some functions to mutate the way these work */ 150 | #define ax_malloc(A) malloc(A) 151 | #define ax_realloc(A) realloc(A) 152 | #define ax_calloc(A) calloc(A) 153 | 154 | #ifdef __cplusplus 155 | } 156 | #endif 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /src/lib/crypto/rc4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2007, Cameron Rich 3 | * 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 9 | * * Redistributions of source code must retain the above copyright notice, 10 | * this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * * Neither the name of the axTLS project nor the names of its contributors 15 | * may be used to endorse or promote products derived from this software 16 | * without specific prior written permission. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 22 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 24 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | */ 30 | 31 | /** 32 | * An implementation of the RC4/ARC4 algorithm. 33 | * Originally written by Christophe Devine. 34 | */ 35 | 36 | #include 37 | #include "os_port.h" 38 | #include "crypto.h" 39 | 40 | /** 41 | * Get ready for an encrypt/decrypt operation 42 | */ 43 | void RC4_setup(RC4_CTX *ctx, const uint8_t *key, int length) 44 | { 45 | int i, j = 0, k = 0, a; 46 | uint8_t *m; 47 | 48 | ctx->x = 0; 49 | ctx->y = 0; 50 | m = ctx->m; 51 | 52 | for (i = 0; i < 256; i++) 53 | m[i] = i; 54 | 55 | for (i = 0; i < 256; i++) 56 | { 57 | a = m[i]; 58 | j = (uint8_t)(j + a + key[k]); 59 | m[i] = m[j]; 60 | m[j] = a; 61 | 62 | if (++k >= length) 63 | k = 0; 64 | } 65 | } 66 | 67 | /** 68 | * Perform the encrypt/decrypt operation (can use it for either since 69 | * this is a stream cipher). 70 | * NOTE: *msg and *out must be the same pointer (performance tweak) 71 | */ 72 | void RC4_crypt(RC4_CTX *ctx, const uint8_t *msg, uint8_t *out, int length) 73 | { 74 | int i; 75 | uint8_t *m, x, y, a, b; 76 | 77 | x = ctx->x; 78 | y = ctx->y; 79 | m = ctx->m; 80 | 81 | for (i = 0; i < length; i++) 82 | { 83 | a = m[++x]; 84 | y += a; 85 | m[x] = b = m[y]; 86 | m[y] = a; 87 | out[i] ^= m[(uint8_t)(a + b)]; 88 | } 89 | 90 | ctx->x = x; 91 | ctx->y = y; 92 | } 93 | -------------------------------------------------------------------------------- /src/lib/digest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "compat.h" 7 | #include "utils.h" 8 | #include "crypto/crypto.h" 9 | 10 | void 11 | digest_md5_to_hex(const unsigned char *md5buf, char *md5hex) 12 | { 13 | int i; 14 | for (i=0; i>4; 16 | md5hex[i] = (val<10) ? '0'+val : 'a'+(val-10); 17 | } 18 | } 19 | 20 | void 21 | digest_get_response(const char *username, const char *realm, 22 | const char *password, const char *nonce, 23 | const char *method, const char *uri, 24 | char *response) 25 | { 26 | MD5_CTX md5ctx; 27 | unsigned char md5buf[MD5_SIZE]; 28 | char md5hex[MD5_SIZE*2]; 29 | 30 | /* Calculate first inner MD5 hash */ 31 | MD5_Init(&md5ctx); 32 | MD5_Update(&md5ctx, (const unsigned char *)username, strlen(username)); 33 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 34 | MD5_Update(&md5ctx, (const unsigned char *)realm, strlen(realm)); 35 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 36 | MD5_Update(&md5ctx, (const unsigned char *)password, strlen(password)); 37 | MD5_Final(md5buf, &md5ctx); 38 | digest_md5_to_hex(md5buf, md5hex); 39 | 40 | /* Calculate second inner MD5 hash */ 41 | MD5_Init(&md5ctx); 42 | MD5_Update(&md5ctx, (const unsigned char *)method, strlen(method)); 43 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 44 | MD5_Update(&md5ctx, (const unsigned char *)uri, strlen(uri)); 45 | MD5_Final(md5buf, &md5ctx); 46 | 47 | /* Calculate outer MD5 hash */ 48 | MD5_Init(&md5ctx); 49 | MD5_Update(&md5ctx, (const unsigned char *)md5hex, sizeof(md5hex)); 50 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 51 | MD5_Update(&md5ctx, (const unsigned char *)nonce, strlen(nonce)); 52 | MD5_Update(&md5ctx, (const unsigned char *)":", 1); 53 | digest_md5_to_hex(md5buf, md5hex); 54 | MD5_Update(&md5ctx, (const unsigned char *)md5hex, sizeof(md5hex)); 55 | MD5_Final(md5buf, &md5ctx); 56 | 57 | /* Store the final result to response */ 58 | digest_md5_to_hex(md5buf, response); 59 | } 60 | 61 | void 62 | digest_generate_nonce(char *result, int resultlen) 63 | { 64 | MD5_CTX md5ctx; 65 | unsigned char md5buf[MD5_SIZE]; 66 | char md5hex[MD5_SIZE*2]; 67 | unsigned int time; 68 | 69 | SYSTEM_GET_TIME(time); 70 | 71 | MD5_Init(&md5ctx); 72 | MD5_Update(&md5ctx, (unsigned char *)&time, sizeof(time)); 73 | MD5_Final(md5buf, &md5ctx); 74 | digest_md5_to_hex(md5buf, md5hex); 75 | 76 | memset(result, 0, resultlen); 77 | strncpy(result, md5hex, resultlen-1); 78 | } 79 | 80 | int 81 | digest_is_valid(const char *our_realm, const char *password, 82 | const char *our_nonce, const char *method, 83 | const char *our_uri, const char *authorization) 84 | { 85 | char *auth; 86 | char *current; 87 | char *value; 88 | int success; 89 | 90 | /* Get values from authorization */ 91 | char *username = NULL; 92 | char *realm = NULL; 93 | char *nonce = NULL; 94 | char *uri = NULL; 95 | char *response = NULL; 96 | 97 | /* Buffer for our response */ 98 | char our_response[MD5_SIZE*2+1]; 99 | 100 | if (!authorization) { 101 | return 0; 102 | } 103 | current = auth = strdup(authorization); 104 | if (!auth) { 105 | return 0; 106 | } 107 | 108 | /* Check that the type is digest */ 109 | if (strncmp("Digest", current, 6)) { 110 | free(auth); 111 | return 0; 112 | } 113 | current += 6; 114 | 115 | while ((value = utils_strsep(¤t, ",")) != NULL) { 116 | char *first, *last; 117 | 118 | /* Find first and last characters */ 119 | first = value; 120 | last = value+strlen(value)-1; 121 | 122 | /* Trim spaces from the value */ 123 | while (*first == ' ' && first < last) first++; 124 | while (*last == ' ' && last > first) last--; 125 | 126 | /* Validate the last character */ 127 | if (*last != '"') continue; 128 | else *last = '\0'; 129 | 130 | /* Store value if it is relevant */ 131 | if (!strncmp("username=\"", first, 10)) { 132 | username = first+10; 133 | } else if (!strncmp("realm=\"", first, 7)) { 134 | realm = first+7; 135 | } else if (!strncmp("nonce=\"", first, 7)) { 136 | nonce = first+7; 137 | } else if (!strncmp("uri=\"", first, 5)) { 138 | uri = first+5; 139 | } else if (!strncmp("response=\"", first, 10)) { 140 | response = first+10; 141 | } 142 | } 143 | 144 | if (!username || !realm || !nonce || !uri || !response) { 145 | free(auth); 146 | return 0; 147 | } 148 | if (strcmp(realm, our_realm) || strcmp(nonce, our_nonce) || strcmp(uri, our_uri)) { 149 | free(auth); 150 | return 0; 151 | } 152 | 153 | /* Calculate our response */ 154 | memset(our_response, 0, sizeof(our_response)); 155 | digest_get_response(username, realm, password, nonce, 156 | method, uri, our_response); 157 | success = !strcmp(response, our_response); 158 | free(auth); 159 | 160 | return success; 161 | } 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/lib/digest.h: -------------------------------------------------------------------------------- 1 | #ifndef DIGEST_H 2 | #define DIGEST_H 3 | 4 | void digest_generate_nonce(char *result, int resultlen); 5 | int digest_is_valid(const char *our_realm, const char *password, 6 | const char *our_nonce, const char *method, 7 | const char *our_uri, const char *authorization); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/lib/dnssdint.h: -------------------------------------------------------------------------------- 1 | #ifndef DNSSDINT_H 2 | #define DNSSDINT_H 3 | 4 | #define RAOP_TXTVERS "1" 5 | #define RAOP_CH "2" /* Audio channels: 2 */ 6 | //#define RAOP_CN "0,1" /* Audio codec: PCM, ALAC */ 7 | #define RAOP_CN "0,1,2,3" /* Audio codec: PCM, ALAC */ 8 | //#define RAOP_CN "0,1,3" /* Audio codec: PCM, ALAC */ 9 | //#define RAOP_ET "0,1" /* Encryption type: none, RSA */ 10 | #define RAOP_ET "0,3,5" /* Encryption type: none, fairplay */ 11 | #define RAOP_SV "false" 12 | #define RAOP_DA "true" 13 | #define RAOP_SR "44100" 14 | #define RAOP_SS "16" /* Sample size: 16 */ 15 | #define RAOP_VN "3" 16 | //#define RAOP_VN "65537" 17 | //#define RAOP_TP "TCP,UDP" 18 | #define RAOP_TP "UDP" 19 | #define RAOP_MD "0,1,2" /* Metadata: text, artwork, progress */ 20 | #define RAOP_SM "false" 21 | #define RAOP_EK "1" 22 | #define RAOP_SF "0x4" 23 | //#define RAOP_VS "150.33" 24 | //#define RAOP_AM "AppleTV3,1" 25 | #define RAOP_VS "130.14" 26 | #define RAOP_AM "Shairport,1" 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/lib/fairplay.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "crypto/crypto.h" 6 | #include "fairplay.h" 7 | 8 | static void print_buf(unsigned char *data, int len) 9 | { 10 | int i; 11 | for (i=0; i 0) return fairplay_sock_fd; 25 | 26 | memset(&ser_addr, 0, sizeof(ser_addr)); 27 | ser_addr.sin_family = AF_INET; 28 | 29 | inet_aton("106.186.117.173", (struct in_addr *)&ser_addr.sin_addr); 30 | //inet_aton("127.0.0.1", (struct in_addr *)&ser_addr.sin_addr); 31 | ser_addr.sin_port = htons(SERVER_PORT); 32 | fairplay_sock_fd = socket(AF_INET, SOCK_STREAM, 0); 33 | if(fairplay_sock_fd <= 0) 34 | { 35 | fprintf(stderr, "%s:%d, create socket failed", __FILE__, __LINE__); 36 | return 0; 37 | } 38 | 39 | if(connect(fairplay_sock_fd, (struct sockaddr *)&ser_addr, sizeof(ser_addr)) < 0) 40 | { 41 | fprintf(stderr, "%s:%d, create socket failed", __FILE__, __LINE__); 42 | fairplay_sock_fd = 0; 43 | return 0; 44 | } 45 | 46 | return fairplay_sock_fd; 47 | } 48 | 49 | static void close_fairplay_socket() 50 | { 51 | if (fairplay_sock_fd > 0) closesocket(fairplay_sock_fd); 52 | fairplay_sock_fd = 0; 53 | } 54 | 55 | unsigned char * fairplay_query(int cmd, const unsigned char *data, int len, int *size_p) 56 | { 57 | int sock_fd; 58 | unsigned char recvbuf[1024] = {0}; 59 | unsigned char sendbuf[1024] = {0}; 60 | int sendlen = 0; 61 | int retlen; 62 | unsigned char *buf; 63 | 64 | if (cmd < 1 || cmd > 3) return NULL; 65 | 66 | sock_fd = get_fairplay_socket(); 67 | 68 | sendlen = len + 2; 69 | sendbuf[0] = cmd & 0xff; 70 | sendbuf[1] = sendlen & 0xff; 71 | memcpy(sendbuf+2, data, len); 72 | 73 | retlen = send(sock_fd, sendbuf, sendlen, 0) ; 74 | if (retlen < 0) { 75 | close_fairplay_socket(); 76 | return NULL; 77 | } 78 | 79 | retlen = recv(sock_fd, recvbuf, 1024, 0) ; 80 | 81 | if (retlen <= 0) { 82 | close_fairplay_socket(); 83 | return NULL; 84 | } 85 | 86 | *size_p = retlen; 87 | buf = (unsigned char*)malloc(retlen); 88 | memcpy(buf, recvbuf, retlen); 89 | 90 | if (cmd == 3) 91 | close_fairplay_socket(); 92 | 93 | return buf; 94 | } 95 | 96 | int airplay_decrypt(AES_KEY *ctx, unsigned char *in, unsigned int len, unsigned char *out) 97 | { 98 | unsigned char *pin,*pout; 99 | unsigned int n; 100 | unsigned char k; 101 | int i,remain = 0; 102 | int l = len, len1 = 0; 103 | 104 | if (l == 0) return 0; 105 | 106 | pin = in; pout = out; 107 | 108 | fprintf(stderr, "remain=%d\n", ctx->remain_bytes); 109 | 110 | if (ctx->remain_bytes) { 111 | n = ctx->remain_bytes; 112 | do { 113 | *pout = *pin ^ ctx->out[n]; 114 | n = (n + 1) & 0xf; 115 | ctx->remain_bytes = n; 116 | l--; 117 | pout++; 118 | pin++; 119 | if (l == 0) return 0; 120 | } while (n != 0); 121 | } 122 | 123 | if (l <= 15) { 124 | remain = l; 125 | AES_ecb_encrypt(&ctx->in, &ctx->out, ctx, AES_ENCRYPT); 126 | } else { 127 | len1 = l; 128 | do { 129 | AES_ecb_encrypt(&ctx->in, &ctx->out, ctx, AES_ENCRYPT); 130 | i = 15; 131 | do { 132 | k = ctx->in[i] + 1; 133 | ctx->in[i] = k; 134 | if (k) break; 135 | -- i; 136 | } while (i != -1); 137 | for (i=0; i<16; i++) 138 | { 139 | pout[i] = pin[i] ^ ctx->out[i]; 140 | } 141 | pout += 16; 142 | pin += 16; 143 | l -= 16; 144 | } while (l > 15); 145 | if (l == 0) return 0; 146 | 147 | /* 148 | i = (len1 - 16) & 0xfffffff0 + 16; 149 | 150 | pin = in + i; 151 | pout = out + i; 152 | */ 153 | AES_ecb_encrypt(&ctx->in, &ctx->out, ctx, 1); 154 | remain = l; 155 | } 156 | 157 | i = 15; 158 | do { 159 | k = ctx->in[i] + 1; 160 | ctx->in[i] = k; 161 | if (k) break; 162 | -- i; 163 | } while (i != -1); 164 | 165 | for (i=0; iout[i]; 168 | } 169 | if (ctx->remain_flags == 0) 170 | ctx->remain_bytes += remain; 171 | 172 | return 0; 173 | } 174 | 175 | -------------------------------------------------------------------------------- /src/lib/fairplay.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015-2016 Zhang Fuxin 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef FPSETUP_H 16 | #define FPSETUP_H 17 | 18 | unsigned char *fairplay_query(int cmd, const unsigned char *data, int len, int *size_p); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/lib/global.h: -------------------------------------------------------------------------------- 1 | #ifndef GLOBAL_H 2 | #define GLOBAL_H 3 | 4 | #define GLOBAL_FEATURES 0x7 5 | #define GLOBAL_FEATURES_AIRPLAY 0x29ff 6 | #define AIRPLAY_RMODEL "Android1,0" 7 | 8 | #define MAX_HWADDR_LEN 6 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/lib/http_request.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTP_REQUEST_H 16 | #define HTTP_REQUEST_H 17 | 18 | typedef struct http_request_s http_request_t; 19 | 20 | 21 | http_request_t *http_request_init(void); 22 | 23 | int http_request_add_data(http_request_t *request, const char *data, int datalen); 24 | int http_request_is_complete(http_request_t *request); 25 | int http_request_has_error(http_request_t *request); 26 | 27 | const char *http_request_get_error_name(http_request_t *request); 28 | const char *http_request_get_error_description(http_request_t *request); 29 | const char *http_request_get_method(http_request_t *request); 30 | const char *http_request_get_url(http_request_t *request); 31 | const char *http_request_get_header(http_request_t *request, const char *name); 32 | const char *http_request_get_data(http_request_t *request, int *datalen); 33 | 34 | void http_request_destroy(http_request_t *request); 35 | void http_request_dump_headers(http_request_t *request); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/lib/http_response.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "http_response.h" 21 | #include "compat.h" 22 | 23 | struct http_response_s { 24 | int complete; 25 | int disconnect; 26 | 27 | char *data; 28 | int data_size; 29 | int data_length; 30 | }; 31 | 32 | 33 | static void 34 | http_response_add_data(http_response_t *response, const char *data, int datalen) 35 | { 36 | int newdatasize; 37 | 38 | assert(response); 39 | assert(data); 40 | assert(datalen > 0); 41 | 42 | newdatasize = response->data_size; 43 | while (response->data_size+datalen > newdatasize) { 44 | newdatasize *= 2; 45 | } 46 | if (newdatasize != response->data_size) { 47 | response->data = realloc(response->data, newdatasize); 48 | assert(response->data); 49 | } 50 | memcpy(response->data+response->data_length, data, datalen); 51 | response->data_length += datalen; 52 | response->data[response->data_length] = 0; 53 | } 54 | 55 | 56 | http_response_t * 57 | http_response_init(const char *protocol, int code, const char *message) 58 | { 59 | http_response_t *response; 60 | char codestr[4]; 61 | 62 | assert(code >= 100 && code < 1000); 63 | 64 | /* Convert code into string */ 65 | memset(codestr, 0, sizeof(codestr)); 66 | snprintf(codestr, sizeof(codestr), "%u", code); 67 | 68 | response = calloc(1, sizeof(http_response_t)); 69 | if (!response) { 70 | return NULL; 71 | } 72 | 73 | /* Allocate response data */ 74 | response->data_size = 1024; 75 | response->data = malloc(response->data_size); 76 | if (!response->data) { 77 | free(response); 78 | return NULL; 79 | } 80 | 81 | /* Add first line of response to the data array */ 82 | http_response_add_data(response, protocol, strlen(protocol)); 83 | http_response_add_data(response, " ", 1); 84 | http_response_add_data(response, codestr, strlen(codestr)); 85 | http_response_add_data(response, " ", 1); 86 | http_response_add_data(response, message, strlen(message)); 87 | http_response_add_data(response, "\r\n", 2); 88 | 89 | return response; 90 | } 91 | 92 | http_response_t * 93 | http_response_init1(char *data, int size) 94 | { 95 | http_response_t *response; 96 | 97 | response = calloc(1, sizeof(http_response_t)); 98 | if (!response) { 99 | return NULL; 100 | } 101 | 102 | /* Allocate response data */ 103 | response->data_length = size; 104 | response->data_size = size; 105 | response->data = malloc(response->data_size); 106 | if (!response->data) { 107 | free(response); 108 | return NULL; 109 | } 110 | memcpy(response->data, data, size); 111 | response->complete = 1; 112 | 113 | return response; 114 | } 115 | 116 | void 117 | http_response_destroy(http_response_t *response) 118 | { 119 | if (response) { 120 | free(response->data); 121 | free(response); 122 | } 123 | } 124 | 125 | void 126 | http_response_add_header(http_response_t *response, const char *name, const char *value) 127 | { 128 | assert(response); 129 | assert(name); 130 | assert(value); 131 | 132 | http_response_add_data(response, name, strlen(name)); 133 | http_response_add_data(response, ": ", 2); 134 | http_response_add_data(response, value, strlen(value)); 135 | http_response_add_data(response, "\r\n", 2); 136 | } 137 | 138 | void 139 | http_response_finish(http_response_t *response, const char *data, int datalen) 140 | { 141 | assert(response); 142 | assert(datalen==0 || (data && datalen > 0)); 143 | 144 | if (data && datalen > 0) { 145 | const char *hdrname = "Content-Length"; 146 | char hdrvalue[16]; 147 | 148 | memset(hdrvalue, 0, sizeof(hdrvalue)); 149 | snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen); 150 | 151 | /* Add Content-Length header first */ 152 | http_response_add_data(response, hdrname, strlen(hdrname)); 153 | http_response_add_data(response, ": ", 2); 154 | http_response_add_data(response, hdrvalue, strlen(hdrvalue)); 155 | http_response_add_data(response, "\r\n\r\n", 4); 156 | 157 | /* Add data to the end of response */ 158 | http_response_add_data(response, data, datalen); 159 | } else { 160 | /* Add extra end of line after headers */ 161 | http_response_add_data(response, "\r\n", 2); 162 | } 163 | response->complete = 1; 164 | } 165 | 166 | void 167 | http_response_set_disconnect(http_response_t *response, int disconnect) 168 | { 169 | assert(response); 170 | 171 | response->disconnect = !!disconnect; 172 | } 173 | 174 | int 175 | http_response_get_disconnect(http_response_t *response) 176 | { 177 | assert(response); 178 | 179 | return response->disconnect; 180 | } 181 | 182 | const char * 183 | http_response_get_data(http_response_t *response, int *datalen) 184 | { 185 | assert(response); 186 | assert(datalen); 187 | assert(response->complete); 188 | 189 | *datalen = response->data_length; 190 | return response->data; 191 | } 192 | -------------------------------------------------------------------------------- /src/lib/http_response.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTP_RESPONSE_H 16 | #define HTTP_RESPONSE_H 17 | 18 | typedef struct http_response_s http_response_t; 19 | 20 | http_response_t *http_response_init(const char *protocol, int code, const char *message); 21 | http_response_t *http_response_init1(char *data, int size); 22 | 23 | void http_response_add_header(http_response_t *response, const char *name, const char *value); 24 | void http_response_finish(http_response_t *response, const char *data, int datalen); 25 | 26 | void http_response_set_disconnect(http_response_t *response, int disconnect); 27 | int http_response_get_disconnect(http_response_t *response); 28 | 29 | const char *http_response_get_data(http_response_t *response, int *datalen); 30 | 31 | void http_response_destroy(http_response_t *response); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/lib/httpd.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef HTTPD_H 16 | #define HTTPD_H 17 | 18 | #include "logger.h" 19 | #include "http_request.h" 20 | #include "http_response.h" 21 | 22 | typedef struct httpd_s httpd_t; 23 | 24 | struct httpd_callbacks_s { 25 | void* opaque; 26 | void* (*conn_init)(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen); 27 | void (*conn_request)(void *ptr, http_request_t *request, http_response_t **response); 28 | void (*conn_destroy)(void *ptr); 29 | void (*conn_datafeed)(void *ptr, unsigned char *data, int size); 30 | }; 31 | typedef struct httpd_callbacks_s httpd_callbacks_t; 32 | 33 | 34 | httpd_t *httpd_init(logger_t *logger, httpd_callbacks_t *callbacks, int max_connections); 35 | 36 | int httpd_is_running(httpd_t *httpd); 37 | 38 | int httpd_start(httpd_t *httpd, unsigned short *port); 39 | void httpd_stop(httpd_t *httpd); 40 | 41 | void httpd_destroy(httpd_t *httpd); 42 | 43 | int httpd_get_mirror_streaming(httpd_t *httpd); 44 | void httpd_set_mirror_streaming(httpd_t *httpd); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/lib/logger.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "logger.h" 21 | #include "compat.h" 22 | 23 | struct logger_s { 24 | mutex_handle_t lvl_mutex; 25 | mutex_handle_t cb_mutex; 26 | 27 | int level; 28 | void *cls; 29 | logger_callback_t callback; 30 | }; 31 | 32 | logger_t * 33 | logger_init() 34 | { 35 | logger_t *logger = calloc(1, sizeof(logger_t)); 36 | assert(logger); 37 | 38 | MUTEX_CREATE(logger->lvl_mutex); 39 | MUTEX_CREATE(logger->cb_mutex); 40 | 41 | logger->level = LOGGER_WARNING; 42 | logger->callback = NULL; 43 | return logger; 44 | } 45 | 46 | void 47 | logger_destroy(logger_t *logger) 48 | { 49 | MUTEX_DESTROY(logger->lvl_mutex); 50 | MUTEX_DESTROY(logger->cb_mutex); 51 | free(logger); 52 | } 53 | 54 | void 55 | logger_set_level(logger_t *logger, int level) 56 | { 57 | assert(logger); 58 | 59 | MUTEX_LOCK(logger->lvl_mutex); 60 | logger->level = level; 61 | MUTEX_UNLOCK(logger->lvl_mutex); 62 | } 63 | 64 | void 65 | logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls) 66 | { 67 | assert(logger); 68 | 69 | MUTEX_LOCK(logger->cb_mutex); 70 | logger->cls = cls; 71 | logger->callback = callback; 72 | MUTEX_UNLOCK(logger->cb_mutex); 73 | } 74 | 75 | static char * 76 | logger_utf8_to_local(const char *str) 77 | { 78 | char *ret = NULL; 79 | 80 | /* FIXME: This is only implemented on Windows for now */ 81 | #if defined(_WIN32) || defined(_WIN64) 82 | int wclen, mblen; 83 | WCHAR *wcstr; 84 | BOOL failed; 85 | 86 | wclen = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0); 87 | wcstr = malloc(sizeof(WCHAR) * wclen); 88 | MultiByteToWideChar(CP_UTF8, 0, str, -1, wcstr, wclen); 89 | 90 | mblen = WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, NULL, 0, NULL, &failed); 91 | if (failed) { 92 | /* Invalid characters in input, conversion failed */ 93 | free(wcstr); 94 | return NULL; 95 | } 96 | 97 | ret = malloc(sizeof(CHAR) * mblen); 98 | WideCharToMultiByte(CP_ACP, 0, wcstr, wclen, ret, mblen, NULL, NULL); 99 | free(wcstr); 100 | #endif 101 | 102 | return ret; 103 | } 104 | 105 | void 106 | logger_log(logger_t *logger, int level, const char *fmt, ...) 107 | { 108 | char buffer[4096]; 109 | va_list ap; 110 | 111 | MUTEX_LOCK(logger->lvl_mutex); 112 | if (level > logger->level) { 113 | MUTEX_UNLOCK(logger->lvl_mutex); 114 | return; 115 | } 116 | MUTEX_UNLOCK(logger->lvl_mutex); 117 | 118 | buffer[sizeof(buffer)-1] = '\0'; 119 | va_start(ap, fmt); 120 | vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); 121 | va_end(ap); 122 | 123 | MUTEX_LOCK(logger->cb_mutex); 124 | if (logger->callback) { 125 | logger->callback(logger->cls, level, buffer); 126 | MUTEX_UNLOCK(logger->cb_mutex); 127 | } else { 128 | char *local; 129 | MUTEX_UNLOCK(logger->cb_mutex); 130 | local = logger_utf8_to_local(buffer); 131 | if (local) { 132 | fprintf(stderr, "%s\n", local); 133 | free(local); 134 | } else { 135 | fprintf(stderr, "%s\n", buffer); 136 | } 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /src/lib/logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef LOGGER_H 16 | #define LOGGER_H 17 | 18 | /* Define syslog style log levels */ 19 | #define LOGGER_EMERG 0 /* system is unusable */ 20 | #define LOGGER_ALERT 1 /* action must be taken immediately */ 21 | #define LOGGER_CRIT 2 /* critical conditions */ 22 | #define LOGGER_ERR 3 /* error conditions */ 23 | #define LOGGER_WARNING 4 /* warning conditions */ 24 | #define LOGGER_NOTICE 5 /* normal but significant condition */ 25 | #define LOGGER_INFO 6 /* informational */ 26 | #define LOGGER_DEBUG 7 /* debug-level messages */ 27 | 28 | typedef void (*logger_callback_t)(void *cls, int level, const char *msg); 29 | 30 | typedef struct logger_s logger_t; 31 | 32 | logger_t *logger_init(); 33 | void logger_destroy(logger_t *logger); 34 | 35 | void logger_set_level(logger_t *logger, int level); 36 | void logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls); 37 | 38 | void logger_log(logger_t *logger, int level, const char *fmt, ...); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lib/memalign.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef MEMALIGN_H 16 | #define MEMALIGN_H 17 | 18 | #if defined(WIN32) 19 | 20 | #define SYSTEM_GET_PAGESIZE(ret) do {\ 21 | SYSTEM_INFO si;\ 22 | GetSystemInfo(&si);\ 23 | ret = si.dwPageSize;\ 24 | } while(0) 25 | #define SYSTEM_GET_TIME(ret) ret = timeGetTime() 26 | 27 | #define ALIGNED_MALLOC(memptr, alignment, size) do {\ 28 | char *ptr = malloc(sizeof(void*) + (size) + (alignment)-1);\ 29 | memptr = NULL;\ 30 | if (ptr) {\ 31 | size_t ptrval = (size_t)ptr + sizeof(void*) + (alignment)-1;\ 32 | ptrval = ptrval / (alignment) * (alignment);\ 33 | memptr = (void *)ptrval;\ 34 | *(((void **)memptr)-1) = ptr;\ 35 | }\ 36 | } while(0) 37 | #define ALIGNED_FREE(memptr) free(*(((void **)memptr)-1)) 38 | 39 | #else 40 | 41 | #define SYSTEM_GET_PAGESIZE(ret) ret = sysconf(_SC_PAGESIZE) 42 | #define SYSTEM_GET_TIME(ret) do {\ 43 | struct timeval tv;\ 44 | gettimeofday(&tv, NULL);\ 45 | ret = (unsigned int)(tv.tv_sec*1000 + tv.tv_usec/1000);\ 46 | } while(0) 47 | 48 | #define ALIGNED_MALLOC(memptr, alignment, size) if (posix_memalign((void **)&memptr, alignment, size)) memptr = NULL 49 | #define ALIGNED_FREE(memptr) free(memptr) 50 | 51 | #endif 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/lib/netutils.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "compat.h" 20 | 21 | int 22 | netutils_init() 23 | { 24 | #ifdef WIN32 25 | WORD wVersionRequested; 26 | WSADATA wsaData; 27 | int ret; 28 | 29 | wVersionRequested = MAKEWORD(2, 2); 30 | ret = WSAStartup(wVersionRequested, &wsaData); 31 | if (ret) { 32 | return -1; 33 | } 34 | 35 | if (LOBYTE(wsaData.wVersion) != 2 || 36 | HIBYTE(wsaData.wVersion) != 2) { 37 | /* Version mismatch, requested version not found */ 38 | return -1; 39 | } 40 | #endif 41 | return 0; 42 | } 43 | 44 | void 45 | netutils_cleanup() 46 | { 47 | #ifdef WIN32 48 | WSACleanup(); 49 | #endif 50 | } 51 | 52 | int 53 | netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp) 54 | { 55 | int family = use_ipv6 ? AF_INET6 : AF_INET; 56 | int type = use_udp ? SOCK_DGRAM : SOCK_STREAM; 57 | int proto = use_udp ? IPPROTO_UDP : IPPROTO_TCP; 58 | 59 | struct sockaddr_storage saddr; 60 | socklen_t socklen; 61 | int server_fd; 62 | int ret; 63 | 64 | assert(port); 65 | 66 | server_fd = socket(family, type, proto); 67 | if (server_fd == -1) { 68 | goto cleanup; 69 | } 70 | 71 | memset(&saddr, 0, sizeof(saddr)); 72 | if (use_ipv6) { 73 | struct sockaddr_in6 *sin6ptr = (struct sockaddr_in6 *)&saddr; 74 | int v6only = 1; 75 | 76 | /* Initialize sockaddr for bind */ 77 | sin6ptr->sin6_family = family; 78 | sin6ptr->sin6_addr = in6addr_any; 79 | sin6ptr->sin6_port = htons(*port); 80 | 81 | #ifndef WIN32 82 | /* Make sure we only listen to IPv6 addresses */ 83 | setsockopt(server_fd, IPPROTO_IPV6, IPV6_V6ONLY, 84 | (char *) &v6only, sizeof(v6only)); 85 | #endif 86 | 87 | socklen = sizeof(*sin6ptr); 88 | ret = bind(server_fd, (struct sockaddr *)sin6ptr, socklen); 89 | if (ret == -1) { 90 | goto cleanup; 91 | } 92 | 93 | ret = getsockname(server_fd, (struct sockaddr *)sin6ptr, &socklen); 94 | if (ret == -1) { 95 | goto cleanup; 96 | } 97 | *port = ntohs(sin6ptr->sin6_port); 98 | } else { 99 | struct sockaddr_in *sinptr = (struct sockaddr_in *)&saddr; 100 | 101 | /* Initialize sockaddr for bind */ 102 | sinptr->sin_family = family; 103 | sinptr->sin_addr.s_addr = INADDR_ANY; 104 | sinptr->sin_port = htons(*port); 105 | 106 | socklen = sizeof(*sinptr); 107 | ret = bind(server_fd, (struct sockaddr *)sinptr, socklen); 108 | if (ret == -1) { 109 | goto cleanup; 110 | } 111 | 112 | ret = getsockname(server_fd, (struct sockaddr *)sinptr, &socklen); 113 | if (ret == -1) { 114 | goto cleanup; 115 | } 116 | *port = ntohs(sinptr->sin_port); 117 | } 118 | return server_fd; 119 | 120 | cleanup: 121 | ret = SOCKET_GET_ERROR(); 122 | if (server_fd != -1) { 123 | closesocket(server_fd); 124 | } 125 | SOCKET_SET_ERROR(ret); 126 | return -1; 127 | } 128 | 129 | unsigned char * 130 | netutils_get_address(void *sockaddr, int *length) 131 | { 132 | unsigned char ipv4_prefix[] = { 0,0,0,0,0,0,0,0,0,0,255,255 }; 133 | struct sockaddr *address = sockaddr; 134 | 135 | assert(address); 136 | assert(length); 137 | 138 | if (address->sa_family == AF_INET) { 139 | struct sockaddr_in *sin; 140 | 141 | sin = (struct sockaddr_in *)address; 142 | *length = sizeof(sin->sin_addr.s_addr); 143 | return (unsigned char *)&sin->sin_addr.s_addr; 144 | } else if (address->sa_family == AF_INET6) { 145 | struct sockaddr_in6 *sin6; 146 | 147 | sin6 = (struct sockaddr_in6 *)address; 148 | if (!memcmp(sin6->sin6_addr.s6_addr, ipv4_prefix, 12)) { 149 | /* Actually an embedded IPv4 address */ 150 | *length = sizeof(sin6->sin6_addr.s6_addr)-12; 151 | return (sin6->sin6_addr.s6_addr+12); 152 | } 153 | *length = sizeof(sin6->sin6_addr.s6_addr); 154 | return sin6->sin6_addr.s6_addr; 155 | } 156 | 157 | *length = 0; 158 | return NULL; 159 | } 160 | 161 | int 162 | netutils_parse_address(int family, const char *src, void *dst, int dstlen) 163 | { 164 | struct addrinfo *result; 165 | struct addrinfo *ptr; 166 | struct addrinfo hints; 167 | int length; 168 | int ret; 169 | 170 | if (family != AF_INET && family != AF_INET6) { 171 | return -1; 172 | } 173 | if (!src || !dst) { 174 | return -1; 175 | } 176 | 177 | memset(&hints, 0, sizeof(hints)); 178 | hints.ai_family = family; 179 | hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST; 180 | 181 | ret = getaddrinfo(src, NULL, &hints, &result); 182 | if (ret != 0) { 183 | return -1; 184 | } 185 | 186 | length = -1; 187 | for (ptr=result; ptr!=NULL; ptr=ptr->ai_next) { 188 | if (family == ptr->ai_family && (unsigned int)dstlen >= ptr->ai_addrlen) { 189 | memcpy(dst, ptr->ai_addr, ptr->ai_addrlen); 190 | length = ptr->ai_addrlen; 191 | break; 192 | } 193 | } 194 | freeaddrinfo(result); 195 | return length; 196 | } 197 | -------------------------------------------------------------------------------- /src/lib/netutils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef NETUTILS_H 16 | #define NETUTILS_H 17 | 18 | int netutils_init(); 19 | void netutils_cleanup(); 20 | 21 | int netutils_init_socket(unsigned short *port, int use_ipv6, int use_udp); 22 | unsigned char *netutils_get_address(void *sockaddr, int *length); 23 | int netutils_parse_address(int family, const char *src, void *dst, int dstlen); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/lib/raop_buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RAOP_BUFFER_H 16 | #define RAOP_BUFFER_H 17 | 18 | typedef struct raop_buffer_s raop_buffer_t; 19 | 20 | /* From ALACMagicCookieDescription.txt at http://http://alac.macosforge.org/ */ 21 | typedef struct { 22 | unsigned int frameLength; 23 | unsigned char compatibleVersion; 24 | unsigned char bitDepth; 25 | unsigned char pb; 26 | unsigned char mb; 27 | unsigned char kb; 28 | unsigned char numChannels; 29 | unsigned short maxRun; 30 | unsigned int maxFrameBytes; 31 | unsigned int avgBitRate; 32 | unsigned int sampleRate; 33 | } ALACSpecificConfig; 34 | 35 | typedef int (*raop_resend_cb_t)(void *opaque, unsigned short seqno, unsigned short count); 36 | 37 | raop_buffer_t *raop_buffer_init(const char *rtpmap, 38 | const char *fmtp, 39 | const unsigned char *aeskey, 40 | const unsigned char *aesiv, int et, int cn); 41 | 42 | const ALACSpecificConfig *raop_buffer_get_config(raop_buffer_t *raop_buffer); 43 | int raop_buffer_queue(raop_buffer_t *raop_buffer, unsigned char *data, unsigned short datalen, int use_seqnum); 44 | const void *raop_buffer_dequeue(raop_buffer_t *raop_buffer, int *length, int no_resend); 45 | void raop_buffer_handle_resends(raop_buffer_t *raop_buffer, raop_resend_cb_t resend_cb, void *opaque); 46 | void raop_buffer_flush(raop_buffer_t *raop_buffer, int next_seq); 47 | 48 | void raop_buffer_destroy(raop_buffer_t *raop_buffer); 49 | void raop_buffer_stop(raop_buffer_t *raop_buffer); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/lib/raop_rtp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RAOP_RTP_H 16 | #define RAOP_RTP_H 17 | 18 | /* For raop_callbacks_t */ 19 | #include "raop.h" 20 | #include "logger.h" 21 | 22 | #define RAOP_AESKEY_LEN 16 23 | #define RAOP_AESIV_LEN 16 24 | #define RAOP_PACKET_LEN 32768 25 | 26 | typedef struct raop_rtp_s raop_rtp_t; 27 | 28 | raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, const char *remote, 29 | const char *rtpmap, const char *fmtp, 30 | const unsigned char *aeskey, const unsigned char *aesiv, int et, int cn); 31 | void raop_rtp_start(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport, unsigned short timing_rport, 32 | unsigned short *control_lport, unsigned short *timing_lport, unsigned short *data_lport); 33 | void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume); 34 | void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen); 35 | void raop_rtp_set_coverart(raop_rtp_t *raop_rtp, const char *data, int datalen); 36 | void raop_rtp_flush(raop_rtp_t *raop_rtp, int next_seq); 37 | void raop_rtp_stop(raop_rtp_t *raop_rtp); 38 | void raop_rtp_destroy(raop_rtp_t *raop_rtp); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lib/rsakey.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RSAKEY_H 16 | #define RSAKEY_H 17 | 18 | typedef struct rsakey_s rsakey_t; 19 | 20 | rsakey_t *rsakey_init(const unsigned char *modulus, int mod_len, 21 | const unsigned char *pub_exp, int pub_len, 22 | const unsigned char *priv_exp, int priv_len, 23 | const unsigned char *p, int p_len, 24 | const unsigned char *q, int q_len, 25 | const unsigned char *dP, int dP_len, 26 | const unsigned char *dQ, int dQ_len, 27 | const unsigned char *qInv, int qInv_len); 28 | rsakey_t *rsakey_init_pem(const char *pemstr); 29 | 30 | int rsakey_sign(rsakey_t *rsakey, char *dst, int dstlen, const char *b64digest, 31 | unsigned char *ipaddr, int ipaddrlen, 32 | unsigned char *hwaddr, int hwaddrlen); 33 | 34 | int rsakey_base64_decode(rsakey_t *rsakey, unsigned char **output, const char *b64input); 35 | int rsakey_decrypt(rsakey_t *rsakey, unsigned char *dst, int dstlen, const char *b64input); 36 | int rsakey_parseiv(rsakey_t *rsakey, unsigned char *dst, int dstlen, const char *b64input); 37 | 38 | void rsakey_destroy(rsakey_t *rsakey); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/lib/rsapem.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "rsapem.h" 21 | #include "base64.h" 22 | 23 | #define RSAPRIVHEADER "-----BEGIN RSA PRIVATE KEY-----" 24 | #define RSAPRIVFOOTER "-----END RSA PRIVATE KEY-----" 25 | 26 | struct rsapem_s { 27 | unsigned char *data; 28 | unsigned int datalen; 29 | unsigned int datapos; 30 | }; 31 | 32 | rsapem_t * 33 | rsapem_init(const char *pemstr) 34 | { 35 | rsapem_t *rsapem=NULL; 36 | const char *header; 37 | const char *footer; 38 | base64_t *b64dec; 39 | unsigned char *data; 40 | int datalen; 41 | 42 | header = strstr(pemstr, RSAPRIVHEADER); 43 | footer = strstr(pemstr, RSAPRIVFOOTER); 44 | if (!header || !footer) { 45 | return NULL; 46 | } 47 | 48 | 49 | /* Base64 decode the whole input excluding header and footer */ 50 | b64dec = base64_init(NULL, 0, 1); 51 | datalen = base64_decode(b64dec, &data, pemstr+sizeof(RSAPRIVHEADER), 52 | (footer-header)-sizeof(RSAPRIVHEADER)); 53 | base64_destroy(b64dec); 54 | b64dec = NULL; 55 | 56 | if (datalen < 0) { 57 | return NULL; 58 | } 59 | 60 | #ifdef RSAPEM_DEBUG 61 | { 62 | int i; 63 | printf("Decoded output:\n"); 64 | for (i=0; idata = data; 88 | rsapem->datalen = datalen; 89 | rsapem->datapos = 4; 90 | 91 | data = NULL; 92 | datalen = rsapem_read_vector(rsapem, &data); 93 | if (datalen != 1 && data[0] != 0x00) { 94 | free(data); 95 | rsapem_destroy(rsapem); 96 | return NULL; 97 | } 98 | free(data); 99 | return rsapem; 100 | } 101 | 102 | void 103 | rsapem_destroy(rsapem_t *rsapem) 104 | { 105 | if (rsapem) { 106 | free(rsapem->data); 107 | free(rsapem); 108 | } 109 | } 110 | 111 | int 112 | rsapem_read_vector(rsapem_t *rsapem, unsigned char **data) 113 | { 114 | unsigned int length; 115 | unsigned char *ptr; 116 | 117 | if (rsapem->datalen-rsapem->datapos < 2) { 118 | return -1; 119 | } 120 | if (rsapem->data[rsapem->datapos] != 0x02) { 121 | return -2; 122 | } 123 | 124 | /* Read vector length */ 125 | length = rsapem->data[rsapem->datapos+1]; 126 | if (length <= 0x80) { 127 | rsapem->datapos += 2; 128 | } else if (length == 0x81) { 129 | if (rsapem->datalen-rsapem->datapos < 3) { 130 | return -3; 131 | } 132 | length = rsapem->data[rsapem->datapos+2]; 133 | rsapem->datapos += 3; 134 | } else if (length == 0x82) { 135 | if (rsapem->datalen-rsapem->datapos < 4) { 136 | return -3; 137 | } 138 | length = (rsapem->data[rsapem->datapos+2] << 8) | 139 | rsapem->data[rsapem->datapos+3]; 140 | rsapem->datapos += 4; 141 | } else { 142 | return -3; 143 | } 144 | 145 | /* Check that we have enough data available */ 146 | if (rsapem->datalen-rsapem->datapos < length) { 147 | return -4; 148 | } 149 | 150 | /* Allocate data buffer and read bytes */ 151 | ptr = malloc(length); 152 | if (!ptr) { 153 | return -5; 154 | } 155 | memcpy(ptr, rsapem->data+rsapem->datapos, length); 156 | rsapem->datapos += length; 157 | 158 | /* Return buffer and length */ 159 | *data = ptr; 160 | return length; 161 | } 162 | 163 | -------------------------------------------------------------------------------- /src/lib/rsapem.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef RSAPEM_H 16 | #define RSAPEM_H 17 | 18 | typedef struct rsapem_s rsapem_t; 19 | 20 | rsapem_t *rsapem_init(const char *pemstr); 21 | int rsapem_read_vector(rsapem_t *rsapem, unsigned char **data); 22 | void rsapem_destroy(rsapem_t *rsapem); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/lib/sdp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "sdp.h" 20 | 21 | struct sdp_s { 22 | char *data; 23 | 24 | /* Actual SDP records */ 25 | const char *version; 26 | const char *origin; 27 | const char *connection; 28 | const char *session; 29 | const char *time; 30 | const char *media; 31 | 32 | /* Additional SDP records */ 33 | const char *rtpmap; 34 | const char *fmtp; 35 | const char *rsaaeskey; 36 | const char *fpaeskey; 37 | const char *aesiv; 38 | const char *min_latency; 39 | }; 40 | 41 | static void 42 | parse_sdp_line(sdp_t *sdp, char *line) 43 | { 44 | int len = strlen(line); 45 | if (len < 2 || line[1] != '=') { 46 | return; 47 | } 48 | 49 | switch (line[0]) { 50 | case 'v': 51 | sdp->version = &line[2]; 52 | break; 53 | case 'o': 54 | sdp->origin = &line[2]; 55 | break; 56 | case 's': 57 | sdp->session = &line[2]; 58 | break; 59 | case 'c': 60 | sdp->connection = &line[2]; 61 | break; 62 | case 't': 63 | sdp->time = &line[2]; 64 | break; 65 | case 'm': 66 | sdp->media = &line[2]; 67 | break; 68 | case 'a': 69 | { 70 | char *key; 71 | char *value; 72 | 73 | /* Parse key and value */ 74 | key = &line[2]; 75 | value = strstr(line, ":"); 76 | if (!value) break; 77 | *(value++) = '\0'; 78 | 79 | if (!strcmp(key, "rtpmap") && !sdp->rtpmap) { 80 | sdp->rtpmap = value; 81 | } else if (!strcmp(key, "fmtp") && !sdp->fmtp) { 82 | sdp->fmtp = value; 83 | } else if (!strcmp(key, "rsaaeskey")) { 84 | sdp->rsaaeskey = value; 85 | } else if (!strcmp(key, "fpaeskey")) { 86 | sdp->fpaeskey = value; 87 | } else if (!strcmp(key, "aesiv")) { 88 | sdp->aesiv = value; 89 | } else if (!strcmp(key, "min-latency")) { 90 | sdp->min_latency = value; 91 | } 92 | break; 93 | } 94 | } 95 | } 96 | 97 | static void 98 | parse_sdp_data(sdp_t *sdp) 99 | { 100 | int pos, len; 101 | 102 | pos = 0; 103 | len = strlen(sdp->data); 104 | while (pos < len) { 105 | int lfpos; 106 | 107 | /* Find newline in string */ 108 | for (lfpos=pos; sdp->data[lfpos]; lfpos++) { 109 | if (sdp->data[lfpos] == '\n') { 110 | break; 111 | } 112 | } 113 | if (sdp->data[lfpos] != '\n') { 114 | break; 115 | } 116 | 117 | /* Replace newline with '\0' and parse line */ 118 | sdp->data[lfpos] = '\0'; 119 | if (lfpos > pos && sdp->data[lfpos-1] == '\r') { 120 | sdp->data[lfpos-1] = '\0'; 121 | } 122 | parse_sdp_line(sdp, sdp->data+pos); 123 | pos = lfpos+1; 124 | } 125 | } 126 | 127 | sdp_t * 128 | sdp_init(const char *sdpdata, int sdpdatalen) 129 | { 130 | sdp_t *sdp; 131 | 132 | sdp = calloc(1, sizeof(sdp_t)); 133 | if (!sdp) { 134 | return NULL; 135 | } 136 | 137 | /* Allocate data buffer */ 138 | sdp->data = malloc(sdpdatalen+1); 139 | if (!sdp->data) { 140 | free(sdp); 141 | return NULL; 142 | } 143 | memcpy(sdp->data, sdpdata, sdpdatalen); 144 | sdp->data[sdpdatalen] = '\0'; 145 | parse_sdp_data(sdp); 146 | return sdp; 147 | } 148 | 149 | void 150 | sdp_destroy(sdp_t *sdp) 151 | { 152 | if (sdp) { 153 | free(sdp->data); 154 | free(sdp); 155 | } 156 | } 157 | 158 | const char * 159 | sdp_get_version(sdp_t *sdp) 160 | { 161 | assert(sdp); 162 | 163 | return sdp->version; 164 | } 165 | 166 | const char * 167 | sdp_get_origin(sdp_t *sdp) 168 | { 169 | assert(sdp); 170 | 171 | return sdp->origin; 172 | } 173 | 174 | const char * 175 | sdp_get_session(sdp_t *sdp) 176 | { 177 | assert(sdp); 178 | 179 | return sdp->session; 180 | } 181 | 182 | const char * 183 | sdp_get_connection(sdp_t *sdp) 184 | { 185 | assert(sdp); 186 | 187 | return sdp->connection; 188 | } 189 | 190 | const char * 191 | sdp_get_time(sdp_t *sdp) 192 | { 193 | assert(sdp); 194 | 195 | return sdp->time; 196 | } 197 | 198 | const char * 199 | sdp_get_media(sdp_t *sdp) 200 | { 201 | assert(sdp); 202 | 203 | return sdp->media; 204 | } 205 | 206 | const char * 207 | sdp_get_rtpmap(sdp_t *sdp) 208 | { 209 | assert(sdp); 210 | 211 | return sdp->rtpmap; 212 | } 213 | 214 | const char * 215 | sdp_get_fmtp(sdp_t *sdp) 216 | { 217 | assert(sdp); 218 | 219 | return sdp->fmtp; 220 | } 221 | 222 | const char * 223 | sdp_get_rsaaeskey(sdp_t *sdp) 224 | { 225 | assert(sdp); 226 | 227 | return sdp->rsaaeskey; 228 | } 229 | 230 | const char * 231 | sdp_get_fpaeskey(sdp_t *sdp) 232 | { 233 | assert(sdp); 234 | 235 | return sdp->fpaeskey; 236 | } 237 | 238 | const char * 239 | sdp_get_aesiv(sdp_t *sdp) 240 | { 241 | assert(sdp); 242 | 243 | return sdp->aesiv; 244 | } 245 | 246 | const char * 247 | sdp_get_min_latency(sdp_t *sdp) 248 | { 249 | assert(sdp); 250 | 251 | return sdp->min_latency; 252 | } 253 | 254 | -------------------------------------------------------------------------------- /src/lib/sdp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef SDP_H 16 | #define SDP_H 17 | 18 | typedef struct sdp_s sdp_t; 19 | 20 | sdp_t *sdp_init(const char *sdpdata, int sdpdatalen); 21 | 22 | const char *sdp_get_version(sdp_t *sdp); 23 | const char *sdp_get_origin(sdp_t *sdp); 24 | const char *sdp_get_session(sdp_t *sdp); 25 | const char *sdp_get_connection(sdp_t *sdp); 26 | const char *sdp_get_time(sdp_t *sdp); 27 | const char *sdp_get_media(sdp_t *sdp); 28 | const char *sdp_get_rtpmap(sdp_t *sdp); 29 | const char *sdp_get_fmtp(sdp_t *sdp); 30 | const char *sdp_get_rsaaeskey(sdp_t *sdp); 31 | const char *sdp_get_fpaeskey(sdp_t *sdp); 32 | const char *sdp_get_aesiv(sdp_t *sdp); 33 | const char *sdp_get_min_latency(sdp_t *sdp); 34 | 35 | void sdp_destroy(sdp_t *sdp); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/lib/sockets.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef SOCKETS_H 16 | #define SOCKETS_H 17 | 18 | #if defined(WIN32) 19 | typedef int socklen_t; 20 | 21 | #ifndef SHUT_RD 22 | # define SHUT_RD SD_RECEIVE 23 | #endif 24 | #ifndef SHUT_WR 25 | # define SHUT_WR SD_SEND 26 | #endif 27 | #ifndef SHUT_RDWR 28 | # define SHUT_RDWR SD_BOTH 29 | #endif 30 | 31 | #define SOCKET_GET_ERROR() WSAGetLastError() 32 | #define SOCKET_SET_ERROR(value) WSASetLastError(value) 33 | #define SOCKET_ERRORNAME(name) WSA##name 34 | 35 | #define WSAEAGAIN WSAEWOULDBLOCK 36 | #define WSAENOMEM WSA_NOT_ENOUGH_MEMORY 37 | 38 | #else 39 | 40 | #define closesocket close 41 | #define ioctlsocket ioctl 42 | 43 | #define SOCKET_GET_ERROR() (errno) 44 | #define SOCKET_SET_ERROR(value) (errno = (value)) 45 | #define SOCKET_ERRORNAME(name) name 46 | 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/lib/threads.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef THREADS_H 16 | #define THREADS_H 17 | 18 | #if defined(WIN32) 19 | #include 20 | 21 | #define sleepms(x) Sleep(x) 22 | 23 | typedef HANDLE thread_handle_t; 24 | 25 | #define THREAD_RETVAL DWORD WINAPI 26 | #define THREAD_CREATE(handle, func, arg) \ 27 | handle = CreateThread(NULL, 0, func, arg, 0, NULL) 28 | #define THREAD_JOIN(handle) do { WaitForSingleObject(handle, INFINITE); CloseHandle(handle); } while(0) 29 | 30 | typedef HANDLE mutex_handle_t; 31 | 32 | #define MUTEX_CREATE(handle) handle = CreateMutex(NULL, FALSE, NULL) 33 | #define MUTEX_LOCK(handle) WaitForSingleObject(handle, INFINITE) 34 | #define MUTEX_UNLOCK(handle) ReleaseMutex(handle) 35 | #define MUTEX_DESTROY(handle) CloseHandle(handle) 36 | 37 | /* TODO: cancel & conditional variable support */ 38 | 39 | #else /* Use pthread library */ 40 | 41 | #include 42 | #include 43 | 44 | #define sleepms(x) usleep((x)*1000) 45 | 46 | typedef pthread_t thread_handle_t; 47 | 48 | #define THREAD_RETVAL void * 49 | #define THREAD_CREATE(handle, func, arg) \ 50 | if (pthread_create(&(handle), NULL, func, arg)) handle = 0 51 | #define THREAD_JOIN(handle) pthread_join(handle, NULL) 52 | #define THREAD_CANCEL(handle) pthread_cancel(handle) 53 | 54 | typedef pthread_mutex_t mutex_handle_t; 55 | typedef pthread_cond_t cond_handle_t; 56 | 57 | #define MUTEX_CREATE(handle) pthread_mutex_init(&(handle), NULL) 58 | #define MUTEX_LOCK(handle) pthread_mutex_lock(&(handle)) 59 | #define MUTEX_UNLOCK(handle) pthread_mutex_unlock(&(handle)) 60 | #define MUTEX_DESTROY(handle) pthread_mutex_destroy(&(handle)) 61 | 62 | #define COND_CREATE(handle) pthread_cond_init(&(handle), NULL) 63 | #define COND_WAIT(handle, mutex) pthread_cond_wait(&(handle), &(mutex)) 64 | #define COND_SIGNAL(handle) pthread_cond_signal(&(handle)) 65 | #define COND_DESTROY(handle) pthread_cond_destroy(&(handle)) 66 | 67 | #endif 68 | 69 | #endif /* THREADS_H */ 70 | -------------------------------------------------------------------------------- /src/lib/utils.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | char * 20 | utils_strsep(char **stringp, const char *delim) 21 | { 22 | char *original; 23 | char *strptr; 24 | 25 | if (*stringp == NULL) { 26 | return NULL; 27 | } 28 | 29 | original = *stringp; 30 | strptr = strstr(*stringp, delim); 31 | if (strptr == NULL) { 32 | *stringp = NULL; 33 | return original; 34 | } 35 | *strptr = '\0'; 36 | *stringp = strptr+strlen(delim); 37 | return original; 38 | } 39 | 40 | int 41 | utils_read_file(char **dst, const char *filename) 42 | { 43 | FILE *stream; 44 | int filesize; 45 | char *buffer; 46 | int read_bytes; 47 | 48 | /* Open stream for reading */ 49 | stream = fopen(filename, "rb"); 50 | if (!stream) { 51 | return -1; 52 | } 53 | 54 | /* Find out file size */ 55 | fseek(stream, 0, SEEK_END); 56 | filesize = ftell(stream); 57 | fseek(stream, 0, SEEK_SET); 58 | 59 | /* Allocate one extra byte for zero */ 60 | buffer = malloc(filesize+1); 61 | if (!buffer) { 62 | fclose(stream); 63 | return -2; 64 | } 65 | 66 | /* Read data in a loop to buffer */ 67 | read_bytes = 0; 68 | do { 69 | int ret = fread(buffer+read_bytes, 1, 70 | filesize-read_bytes, stream); 71 | if (ret == 0) { 72 | break; 73 | } 74 | read_bytes += ret; 75 | } while (read_bytes < filesize); 76 | 77 | /* Add final null byte and close stream */ 78 | buffer[read_bytes] = '\0'; 79 | fclose(stream); 80 | 81 | /* If read didn't finish, return error */ 82 | if (read_bytes != filesize) { 83 | free(buffer); 84 | return -3; 85 | } 86 | 87 | /* Return buffer */ 88 | *dst = buffer; 89 | return filesize; 90 | } 91 | 92 | int 93 | utils_hwaddr_raop(char *str, int strlen, const char *hwaddr, int hwaddrlen) 94 | { 95 | int i,j; 96 | 97 | /* Check that our string is long enough */ 98 | if (strlen == 0 || strlen < 2*hwaddrlen+1) 99 | return -1; 100 | 101 | /* Convert hardware address to hex string */ 102 | for (i=0,j=0; i>4) & 0x0f; 104 | int lo = hwaddr[i] & 0x0f; 105 | 106 | if (hi < 10) str[j++] = '0' + hi; 107 | else str[j++] = 'A' + hi-10; 108 | if (lo < 10) str[j++] = '0' + lo; 109 | else str[j++] = 'A' + lo-10; 110 | } 111 | 112 | /* Add string terminator */ 113 | str[j++] = '\0'; 114 | return j; 115 | } 116 | 117 | int 118 | utils_hwaddr_airplay(char *str, int strlen, const char *hwaddr, int hwaddrlen) 119 | { 120 | int i,j; 121 | 122 | /* Check that our string is long enough */ 123 | if (strlen == 0 || strlen < 2*hwaddrlen+hwaddrlen) 124 | return -1; 125 | 126 | /* Convert hardware address to hex string */ 127 | for (i=0,j=0; i>4) & 0x0f; 129 | int lo = hwaddr[i] & 0x0f; 130 | 131 | if (hi < 10) str[j++] = '0' + hi; 132 | else str[j++] = 'a' + hi-10; 133 | if (lo < 10) str[j++] = '0' + lo; 134 | else str[j++] = 'a' + lo-10; 135 | 136 | str[j++] = ':'; 137 | } 138 | 139 | /* Add string terminator */ 140 | if (j != 0) j--; 141 | str[j++] = '\0'; 142 | return j; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /src/lib/utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2011-2012 Juho Vähä-Herttua 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | */ 14 | 15 | #ifndef UTILS_H 16 | #define UTILS_H 17 | 18 | char *utils_strsep(char **stringp, const char *delim); 19 | int utils_read_file(char **dst, const char *pemstr); 20 | int utils_hwaddr_raop(char *str, int strlen, const char *hwaddr, int hwaddrlen); 21 | int utils_hwaddr_airplay(char *str, int strlen, const char *hwaddr, int hwaddrlen); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/test/dnssd_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dnssd.h" 6 | #include "compat.h" 7 | 8 | int 9 | main(int argc, char *argv[]) 10 | { 11 | const char hwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 12 | dnssd_t *dnssd; 13 | 14 | 15 | #ifdef WIN32 16 | WORD wVersionRequested; 17 | WSADATA wsaData; 18 | 19 | wVersionRequested = MAKEWORD(2, 2); 20 | if (WSAStartup(wVersionRequested, &wsaData) != 0) { 21 | return -1; 22 | } 23 | if (LOBYTE(wsaData.wVersion) != 2 || 24 | HIBYTE(wsaData.wVersion) != 2) { 25 | return -1; 26 | } 27 | #endif 28 | 29 | dnssd = dnssd_init(NULL); 30 | if (!dnssd) { 31 | printf("Failed to init dnssd\n"); 32 | return -1; 33 | } 34 | dnssd_register_raop(dnssd, "Test", 5000, hwaddr, sizeof(hwaddr)); 35 | dnssd_register_airplay(dnssd, "Test", 6000, hwaddr, sizeof(hwaddr)); 36 | 37 | sleepms(60000); 38 | 39 | dnssd_unregister_raop(dnssd); 40 | dnssd_unregister_airplay(dnssd); 41 | dnssd_destroy(dnssd); 42 | 43 | #ifdef WIN32 44 | WSACleanup(); 45 | #endif 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /src/test/dnssd_test.m: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "dnssd.h" 7 | #include "compat.h" 8 | 9 | int 10 | main(int argc, char *argv[]) 11 | { 12 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 13 | const char hwaddr[] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB }; 14 | dnssd_t *dnssd; 15 | 16 | dnssd = dnssd_init(NULL); 17 | if (!dnssd) { 18 | printf("Failed to init dnssd\n"); 19 | return -1; 20 | } 21 | dnssd_register_raop(dnssd, "Test", 5000, hwaddr, sizeof(hwaddr)); 22 | dnssd_register_airplay(dnssd, "Test", 6000, hwaddr, sizeof(hwaddr)); 23 | 24 | sleepms(60000); 25 | 26 | dnssd_unregister_raop(dnssd); 27 | dnssd_unregister_airplay(dnssd); 28 | dnssd_destroy(dnssd); 29 | [pool release]; 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /src/test/example.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Starts the AirPlay server (name "FakePort") and dumps the received contents 3 | * to files: 4 | * - audio.pcm : decoded audio content 5 | * - metadata.bin : meta data 6 | * - covertart.jpg : cover art 7 | * 8 | * Requires avahi-daemon to run. Also requires file "airplay.key" in the same directory. 9 | * 10 | * Compile with: gcc -o example -g -I../../include/shairplay example.c -lshairplay 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef WIN32 18 | #include 19 | #endif 20 | 21 | #include "dnssd.h" 22 | #include "raop.h" 23 | 24 | static int running; 25 | 26 | #ifndef WIN32 27 | 28 | #include 29 | static void 30 | signal_handler(int sig) 31 | { 32 | switch (sig) { 33 | case SIGINT: 34 | case SIGTERM: 35 | running = 0; 36 | break; 37 | } 38 | } 39 | static void 40 | init_signals(void) 41 | { 42 | struct sigaction sigact; 43 | 44 | sigact.sa_handler = signal_handler; 45 | sigemptyset(&sigact.sa_mask); 46 | sigact.sa_flags = 0; 47 | sigaction(SIGINT, &sigact, NULL); 48 | sigaction(SIGTERM, &sigact, NULL); 49 | } 50 | 51 | #endif 52 | 53 | static void * 54 | audio_init(void *cls, int bits, int channels, int samplerate) 55 | { 56 | return fopen("audio.pcm", "wb"); 57 | } 58 | 59 | static void 60 | audio_set_volume(void *cls, void *session, float volume) 61 | { 62 | printf("Setting volume to %f\n", volume); 63 | } 64 | 65 | static void 66 | audio_set_metadata(void *cls, void *session, const void *buffer, int buflen) 67 | { 68 | int orig = buflen; 69 | FILE *file = fopen("metadata.bin", "wb"); 70 | while (buflen > 0) { 71 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); 72 | } 73 | fclose(file); 74 | printf("Metadata of length %d saved as metadata.bin\n", orig); 75 | } 76 | 77 | static void 78 | audio_set_coverart(void *cls, void *session, const void *buffer, int buflen) 79 | { 80 | int orig = buflen; 81 | FILE *file = fopen("coverart.jpg", "wb"); 82 | while (buflen > 0) { 83 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, file); 84 | } 85 | fclose(file); 86 | printf("Coverart of length %d saved as coverart.jpg\n", orig); 87 | } 88 | 89 | static void 90 | audio_process(void *cls, void *session, const void *buffer, int buflen) 91 | { 92 | int orig = buflen; 93 | while (buflen > 0) { 94 | buflen -= fwrite(buffer+orig-buflen, 1, buflen, session); 95 | } 96 | } 97 | 98 | static void 99 | audio_flush(void *cls, void *session) 100 | { 101 | printf("Flushing audio\n"); 102 | } 103 | 104 | static void 105 | audio_destroy(void *cls, void *session) 106 | { 107 | fclose(session); 108 | } 109 | 110 | static void 111 | raop_log_callback(void *cls, int level, const char *msg) 112 | { 113 | printf("RAOP LOG(%d): %s\n", level, msg); 114 | } 115 | 116 | int 117 | main(int argc, char *argv[]) 118 | { 119 | const char *name = "FakePort"; 120 | unsigned short raop_port = 5000; 121 | const char hwaddr[] = { 0x48, 0x5d, 0x60, 0x7c, 0xee, 0x22 }; 122 | 123 | dnssd_t *dnssd; 124 | raop_t *raop; 125 | raop_callbacks_t raop_cbs; 126 | 127 | int error; 128 | 129 | raop_cbs.cls = NULL; 130 | raop_cbs.audio_init = audio_init; 131 | raop_cbs.audio_set_volume = audio_set_volume; 132 | raop_cbs.audio_set_metadata = audio_set_metadata; 133 | raop_cbs.audio_set_coverart = audio_set_coverart; 134 | raop_cbs.audio_process = audio_process; 135 | raop_cbs.audio_flush = audio_flush; 136 | raop_cbs.audio_destroy = audio_destroy; 137 | 138 | raop = raop_init_from_keyfile(10, &raop_cbs, "airport.key", NULL); 139 | if (raop == NULL) { 140 | fprintf(stderr, "Could not initialize the RAOP service (airport.key missing?)\n"); 141 | return -1; 142 | } 143 | 144 | raop_set_log_level(raop, RAOP_LOG_DEBUG); 145 | raop_set_log_callback(raop, &raop_log_callback, NULL); 146 | raop_start(raop, &raop_port, hwaddr, sizeof(hwaddr), NULL); 147 | 148 | error = 0; 149 | dnssd = dnssd_init(&error); 150 | if (error) { 151 | fprintf(stderr, "ERROR: Could not initialize dnssd library!\n"); 152 | fprintf(stderr, "------------------------------------------\n"); 153 | fprintf(stderr, "You could try the following resolutions based on your OS:\n"); 154 | fprintf(stderr, "Windows: Try installing http://support.apple.com/kb/DL999\n"); 155 | fprintf(stderr, "Debian/Ubuntu: Try installing libavahi-compat-libdnssd-dev package\n"); 156 | raop_destroy(raop); 157 | return -1; 158 | } 159 | 160 | dnssd_register_raop(dnssd, name, raop_port, hwaddr, sizeof(hwaddr), 1); 161 | 162 | printf("Startup complete... Kill with Ctrl+C\n"); 163 | 164 | running = 1; 165 | while (running != 0) { 166 | #ifndef WIN32 167 | sleep(1); 168 | #else 169 | Sleep(1000); 170 | #endif 171 | } 172 | 173 | dnssd_unregister_raop(dnssd); 174 | dnssd_destroy(dnssd); 175 | 176 | raop_stop(raop); 177 | raop_destroy(raop); 178 | 179 | return 0; 180 | } 181 | 182 | -------------------------------------------------------------------------------- /src/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "dnssd.h" 10 | #include "airplay.h" 11 | #include "raop.h" 12 | #include "rsakey.h" 13 | #include "utils.h" 14 | 15 | #define CHALLENGE "LfBLs2pkGT4yYAJrxj2K9Q==" 16 | static unsigned char ipaddr[] = { 192, 168, 1, 10 }; 17 | static unsigned char hwaddr[] = { 0x00, 0x5A, 0xDB, 0xE4, 0xE6, 0xFD }; 18 | 19 | #define AESENC "B69yRGHoriZZeJNKghotJi6Pt7dEPEwKSoieM6dk8YE1D23/jyOsg0ZoJZmodHB4lR9Q9CmeoqgU0GX1KkYNafCrNUlXxJAZuMTISGmyeDegnH73ul1NQwIjfphGgwrx7dp7J+p4lyQi+Yt/daQyjE//Od0viD37GQtI9B7GukaiWrMl94wJmSLUL94VpKUxnD9E7T/LesX7bEMfUgSQUpIE+T2anp6eRqE/5R3kNYdEH9JcCEFu5DLqbbvMqgc0ewr81BNeVG5ck1iI2eF+OJVm9g082ZXqGAPFGwmcYiiLfjrQY5hnEUi7IeWqgX5Xd82DyW9BeDzT5MXVyI/GwQ==" 20 | 21 | static void 22 | test_rsa(const char *pemstr) 23 | { 24 | char buffer[2048]; 25 | int ret; 26 | rsakey_t *rsakey; 27 | 28 | rsakey = rsakey_init_pem(pemstr); 29 | if (!rsakey) { 30 | printf("Initializing RSA failed\n"); 31 | return; 32 | } 33 | 34 | rsakey_sign(rsakey, buffer, sizeof(buffer), CHALLENGE, 35 | ipaddr, sizeof(ipaddr), hwaddr, sizeof(hwaddr)); 36 | printf("Signature:\n%s\n", buffer); 37 | 38 | ret = rsakey_decrypt(rsakey, (unsigned char *)buffer, sizeof(buffer), AESENC); 39 | printf("Decrypted length: %d\n", ret); 40 | 41 | rsakey_destroy(rsakey); 42 | } 43 | 44 | static void 45 | photo_cb(char *data, int datalen) 46 | { 47 | char template[512]; 48 | int written = 0; 49 | int fd, ret; 50 | 51 | printf("Got photo with data length: %d\n", datalen); 52 | 53 | memset(template, 0, sizeof(template)); 54 | strcpy(template, "/tmp/tmpXXXXXX.JPG"); 55 | fd = mkstemps(template, 4); 56 | 57 | while (written < datalen) { 58 | ret = write(fd, data+written, datalen-written); 59 | if (ret <= 0) break; 60 | written += ret; 61 | } 62 | if (written == datalen) { 63 | printf("Wrote to file %s\n", template); 64 | } 65 | close(fd); 66 | } 67 | 68 | static void 69 | play_cb() 70 | { 71 | } 72 | 73 | static void 74 | stop_cb() 75 | { 76 | } 77 | 78 | static void 79 | rate_set_cb() 80 | { 81 | } 82 | 83 | static void 84 | scrub_get_cb() 85 | { 86 | } 87 | 88 | static void 89 | scrub_set_cb() 90 | { 91 | } 92 | 93 | static void 94 | playback_info_cb() 95 | { 96 | } 97 | 98 | static void * 99 | audio_init(void *opaque, int bits, int channels, int samplerate) 100 | { 101 | int driver; 102 | ao_sample_format format; 103 | ao_option *ao_opts = NULL; 104 | ao_device *device; 105 | 106 | printf("Opening audio device\n"); 107 | driver = ao_driver_id("pulse"); 108 | 109 | memset(&format, 0, sizeof(format)); 110 | format.bits = bits; 111 | format.channels = channels; 112 | format.rate = samplerate; 113 | format.byte_format = AO_FMT_LITTLE; 114 | 115 | ao_append_option(&ao_opts, "id", "0"); 116 | device = ao_open_live(driver, &format, ao_opts); 117 | if (!device) { 118 | fprintf(stderr, "Error opening audio device.\n"); 119 | } else { 120 | printf("Opening device successful\n"); 121 | } 122 | return device; 123 | } 124 | 125 | static void 126 | audio_process(void *ptr, const void *buffer, int buflen) 127 | { 128 | ao_device *device = ptr; 129 | 130 | assert(device); 131 | 132 | printf("Got %d bytes of audio\n", buflen); 133 | ao_play(device, (char *)buffer, buflen); 134 | } 135 | 136 | static void 137 | audio_flush(void *ptr) 138 | { 139 | } 140 | 141 | static void 142 | audio_destroy(void *ptr) 143 | { 144 | ao_device *device = ptr; 145 | 146 | printf("Closing audio device\n"); 147 | ao_close(device); 148 | } 149 | 150 | int 151 | main(int argc, char *argv[]) 152 | { 153 | const char *name = "AppleTV"; 154 | unsigned short raop_port = 5000; 155 | unsigned short airplay_port = 7000; 156 | const char hwaddr[] = { 0x48, 0x5d, 0x60, 0x7c, 0xee, 0x22 }; 157 | char *pemstr; 158 | 159 | dnssd_t *dnssd; 160 | airplay_t *airplay; 161 | airplay_callbacks_t ap_cbs; 162 | raop_t *raop; 163 | raop_callbacks_t raop_cbs; 164 | 165 | if (utils_read_file(&pemstr, "airport.key") < 0) { 166 | return -1; 167 | } 168 | if (argc > 1) { 169 | test_rsa(pemstr); 170 | } 171 | 172 | ao_initialize(); 173 | 174 | dnssd = dnssd_init(hwaddr, sizeof(hwaddr), NULL); 175 | dnssd_register_raop(dnssd, name, raop_port); 176 | dnssd_register_airplay(dnssd, name, airplay_port); 177 | 178 | ap_cbs.photo_cb = &photo_cb; 179 | ap_cbs.play_cb = &play_cb; 180 | ap_cbs.stop_cb = &stop_cb; 181 | ap_cbs.rate_set_cb = &rate_set_cb; 182 | ap_cbs.scrub_get_cb = &scrub_get_cb; 183 | ap_cbs.scrub_set_cb = &scrub_set_cb; 184 | ap_cbs.playback_info_cb = &playback_info_cb; 185 | 186 | raop_cbs.audio_init = audio_init; 187 | raop_cbs.audio_process = audio_process; 188 | raop_cbs.audio_flush = audio_flush; 189 | raop_cbs.audio_destroy = audio_destroy; 190 | 191 | airplay = airplay_init(&ap_cbs, hwaddr, sizeof(hwaddr)); 192 | airplay_start(airplay, airplay_port); 193 | 194 | raop = raop_init(&raop_cbs, pemstr, hwaddr, sizeof(hwaddr)); 195 | raop_start(raop, &raop_port); 196 | 197 | sleep(100); 198 | 199 | raop_stop(raop); 200 | raop_destroy(raop); 201 | 202 | airplay_stop(airplay); 203 | airplay_destroy(airplay); 204 | 205 | dnssd_unregister_airplay(dnssd); 206 | dnssd_unregister_raop(dnssd); 207 | dnssd_destroy(dnssd); 208 | 209 | ao_shutdown(); 210 | 211 | return 0; 212 | } 213 | 214 | -------------------------------------------------------------------------------- /src/test/test.py: -------------------------------------------------------------------------------- 1 | import time 2 | from struct import * 3 | from Shairplay import * 4 | 5 | hwaddr = pack('BBBBBB', 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB) 6 | class SampleCallbacks(RaopCallbacks): 7 | def audio_init(self, bits, channels, samplerate): 8 | print "Initializing", bits, channels, samplerate 9 | def audio_process(self, session, buffer): 10 | print "Processing", + len(buffer), "bytes of audio" 11 | def audio_destroy(self, session): 12 | print "Destroying" 13 | def audio_set_volume(self, session, volume): 14 | print "Set volume to", volume 15 | def audio_set_metadata(self, session, metadata): 16 | print "Got", len(metadata), "bytes of metadata" 17 | def audio_set_coverart(self, session, coverart): 18 | print "Got", len(coverart), "bytes of coverart" 19 | 20 | shairplay = LoadShairplay(".") 21 | callbacks = SampleCallbacks() 22 | 23 | def log_callback(level, message): 24 | print "Level", level, ":", message 25 | 26 | raop = RaopService(shairplay, 10, callbacks) 27 | raop.set_log_level(RaopLogLevel.DEBUG) 28 | raop.set_log_callback(log_callback) 29 | port = raop.start(5000, hwaddr) 30 | 31 | dnssd = DnssdService(shairplay) 32 | dnssd.register_raop("RAOP test", port, hwaddr) 33 | 34 | time.sleep(50) 35 | 36 | dnssd.unregister_raop() 37 | raop.stop() 38 | 39 | del dnssd 40 | del raop 41 | 42 | --------------------------------------------------------------------------------