├── .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 |
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 | Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)
45 | Trademarks
46 | Qt Solutions
47 |
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 |
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 | void initialize ( bool dummy = true ) (obsolete)
21 |
22 |
23 | Member Function Documentation
24 | void QtSingleApplication::initialize ( bool dummy = true )
25 |
26 |
27 | Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies)
28 | Trademarks
29 | Qt Solutions
30 |
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 |
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 |
--------------------------------------------------------------------------------