├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── airplay
├── aes.c
├── aes.h
├── aes_ctr.c
├── aes_ctr.h
├── byteutils.c
├── byteutils.h
├── compat.h
├── crypto
│ ├── aes.c
│ ├── bigint.c
│ ├── bigint.h
│ ├── bigint_impl.h
│ ├── config.h
│ ├── crypto.h
│ ├── hmac.c
│ ├── md5.c
│ ├── os_port.h
│ ├── rc4.c
│ └── sha1.c
├── curve25519
│ ├── curve25519-donna.c
│ └── curve25519.h
├── dnssd.c
├── dnssd.h
├── dnssdint.h
├── ed25519
│ ├── add_scalar.c
│ ├── ed25519.h
│ ├── fe.c
│ ├── fe.h
│ ├── fixedint.h
│ ├── ge.c
│ ├── ge.h
│ ├── key_exchange.c
│ ├── keypair.c
│ ├── precomp_data.h
│ ├── sc.c
│ ├── sc.h
│ ├── seed.c
│ ├── sha512.c
│ ├── sha512.h
│ ├── sign.c
│ └── verify.c
├── fairplay.h
├── fairplay_playfair.c
├── global.h
├── http_request.c
├── http_request.h
├── http_response.c
├── http_response.h
├── httpd.c
├── httpd.h
├── llhttp
│ ├── LICENSE-MIT
│ ├── api.c
│ ├── http.c
│ ├── llhttp.c
│ └── llhttp.h
├── logger.c
├── logger.h
├── memalign.h
├── mirror_buffer.c
├── mirror_buffer.h
├── netutils.c
├── netutils.h
├── pairing.c
├── pairing.h
├── playfair
│ ├── LICENSE.md
│ ├── hand_garble.c
│ ├── modified_md5.c
│ ├── omg_hax.c
│ ├── omg_hax.h
│ ├── playfair.c
│ ├── playfair.h
│ └── sap_hash.c
├── plist
│ ├── base64.c
│ ├── base64.h
│ ├── bplist.c
│ ├── bytearray.c
│ ├── bytearray.h
│ ├── cnary.c
│ ├── hashtable.c
│ ├── hashtable.h
│ ├── list.c
│ ├── list.h
│ ├── node.c
│ ├── node.h
│ ├── node_list.c
│ ├── node_list.h
│ ├── object.h
│ ├── plist.c
│ ├── plist.h
│ ├── plist
│ │ └── plist.h
│ ├── ptrarray.c
│ ├── ptrarray.h
│ ├── strbuf.h
│ ├── time64.c
│ ├── time64.h
│ ├── time64_limits.h
│ └── xplist.c
├── raop.c
├── raop.h
├── raop_buffer.c
├── raop_buffer.h
├── raop_handlers.h
├── raop_ntp.c
├── raop_ntp.h
├── raop_rtp.c
├── raop_rtp.h
├── raop_rtp_mirror.c
├── raop_rtp_mirror.h
├── sockets.h
├── stream.h
├── threads.h
├── utils.c
└── utils.h
├── img
├── close.png
├── crop.png
├── display.png
├── opacity.png
├── pause.png
├── pin.png
├── pinned.png
├── play.png
├── pop.png
├── pop_in.png
├── pop_out.png
├── stop.png
├── uncrop.png
└── windows.png
├── package.sh
├── pip.xcodeproj
└── project.pbxproj
├── pip
├── H264Decoder.h
├── H264Decoder.m
├── Media.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ └── pip_512p.png
│ └── Contents.json
├── audioPlayer.h
├── audioPlayer.m
├── cgs.h
├── common.h
├── imageRenderer.h
├── imageView.h
├── imageView.m
├── incbin.h
├── info.plist
├── main.m
├── metalRenderer.m
├── openGLRenderer.m
├── pip.h
├── preferences.h
├── preferences.m
├── receiver.h
├── receiver.m
├── selectionView.h
├── selectionView.m
├── window.h
└── window.m
├── run.sh
└── settings.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## Build generated
6 | build/
7 | .build/
8 | DerivedData/
9 |
10 | ## Various settings
11 | *.pbxuser
12 | !default.pbxuser
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata/
20 | *.xcworkspace
21 |
22 | ## Other
23 | *.moved-aside
24 | *.xccheckout
25 | *.xcscmblueprint
26 |
27 | ## Obj-C/Swift specific
28 | *.hmap
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | # CocoaPods
34 | #
35 | # We recommend against adding the Pods directory to your .gitignore. However
36 | # you should judge for yourself, the pros and cons are mentioned at:
37 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
38 | #
39 | # Pods/
40 |
41 | # Carthage
42 | #
43 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
44 | # Carthage/Checkouts
45 |
46 | Carthage/Build
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
54 |
55 | fastlane/report.xml
56 | fastlane/Preview.html
57 | fastlane/screenshots
58 | fastlane/test_output
59 |
60 | # Code Injection
61 | #
62 | # After new code Injection tools there's a generated folder /iOSInjectionProject
63 | # https://github.com/johnno1962/injectionforxcode
64 |
65 | iOSInjectionProject/
66 |
67 | .DS_Store
68 | *.dmg
69 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.13)
2 |
3 | project(PiP)
4 |
5 | add_compile_options(-fobjc-arc -Wno-deprecated-declarations -Wno-format)
6 |
7 | set(frameworks Cocoa VideoToolbox AudioToolbox CoreMedia QuartzCore OpenGL Metal MetalKit PIP SkyLight)
8 | list(TRANSFORM frameworks PREPEND "-framework ")
9 |
10 | set(AIRPLAY_SUPPORT_ENABLED 1)
11 |
12 | file(GLOB_RECURSE pip_src CONFIGURE_DEPENDS "pip/*.m")
13 | add_executable(pip ${pip_src})
14 | target_include_directories(pip PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
15 | target_link_libraries(pip PUBLIC -fobjc-link-runtime "-F /System/Library/PrivateFrameworks" ${frameworks})
16 |
17 | if(${AIRPLAY_SUPPORT_ENABLED} EQUAL 1)
18 | file(GLOB_RECURSE airplay_src CONFIGURE_DEPENDS "airplay/*.c")
19 | add_library(airplay ${airplay_src})
20 | target_link_libraries(pip PUBLIC airplay)
21 | target_include_directories(pip PRIVATE airplay)
22 | else()
23 | target_compile_definitions(pip PUBLIC NO_AIRPLAY)
24 | endif()
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 amitv87
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # macOS Picture in Picture
2 |
3 |
4 |
5 |
6 |
7 |
8 | Always on top window preview with AirPlay receiver support (if on macOS 12+, turn-off built-in AirPlay receiver from system preferences)
9 |
10 | ## Code Info
11 | * Nibless cocoa app
12 | * OpenGL/Metal renderer with HiDPI support
13 | * CoreGraphics based capturer (looking for alternative)
14 | * No third party dependency
15 | * Uses private framework for native pip support
16 | * AirPlay backend from https://github.com/FDH2/UxPlay and https://github.com/KqSMea8/AirplayServer
17 |
18 | ## Features
19 | * Clone any visibile window
20 | * Clone multiple active display
21 | * Crop the preview
22 | * Auto and manual resize preserving the aspect ratio
23 | * Multiple window preview from same process, ```cmd+n``` to open and ```cmd+w``` to close
24 | * Pinch to zoom
25 | * Native picture in picture support ```cmd+p```
26 | * Transparency/opacity control (slider in right click menu)
27 | * Minimal modern UI
28 | * Upto 10 parallel airplay sessions (soft limit)
29 |
30 | ## Installation
31 |
32 | ### Manual download
33 |
34 |
35 | ### Download and install via Homebrew
36 |
37 | ```
38 | brew install --cask amitv87-pip
39 | ```
40 |
41 | ### Build from source and run
42 | ```
43 | # checkout code
44 | git clone https://github.com/amitv87/PiP.git
45 | cd pip
46 |
47 | # build using xcode
48 | xcodebuild -alltargets
49 | open build/Release/PiP.app
50 |
51 | # or simply
52 | ./run.sh
53 | ```
54 |
--------------------------------------------------------------------------------
/airplay/aes.h:
--------------------------------------------------------------------------------
1 | #ifndef _AES_H_
2 | #define _AES_H_
3 |
4 | #include
5 |
6 | // #define the macros below to 1/0 to enable/disable the mode of operation.
7 | //
8 | // CBC enables AES encryption in CBC-mode of operation.
9 | // CTR enables encryption in counter-mode.
10 | // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously.
11 |
12 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time.
13 | #ifndef CBC
14 | #define CBC 1
15 | #endif
16 |
17 | #ifndef ECB
18 | #define ECB 1
19 | #endif
20 |
21 | #ifndef CTR
22 | #define CTR 1
23 | #endif
24 |
25 |
26 | #define AES128 1
27 | //#define AES192 1
28 | //#define AES256 1
29 |
30 | #define AES_BLOCKLEN 16 //Block length in bytes AES is 128b block only
31 |
32 | #if defined(AES256) && (AES256 == 1)
33 | #define AES_KEYLEN 32
34 | #define AES_keyExpSize 240
35 | #elif defined(AES192) && (AES192 == 1)
36 | #define AES_KEYLEN 24
37 | #define AES_keyExpSize 208
38 | #else
39 | #define AES_KEYLEN 16 // Key length in bytes
40 | #define AES_keyExpSize 176
41 | #endif
42 |
43 | struct AES_ctx
44 | {
45 | uint8_t RoundKey[AES_keyExpSize];
46 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
47 | uint8_t Iv[AES_BLOCKLEN];
48 | #endif
49 | };
50 |
51 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key);
52 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1))
53 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv);
54 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv);
55 | #endif
56 |
57 | #if defined(ECB) && (ECB == 1)
58 | // buffer size is exactly AES_BLOCKLEN bytes;
59 | // you need only AES_init_ctx as IV is not used in ECB
60 | // NB: ECB is considered insecure for most uses
61 | void AES_ECB_encrypt(struct AES_ctx* ctx, uint8_t* buf);
62 | void AES_ECB_decrypt(struct AES_ctx* ctx, uint8_t* buf);
63 |
64 | #endif // #if defined(ECB) && (ECB == !)
65 |
66 |
67 | #if defined(CBC) && (CBC == 1)
68 | // buffer size MUST be mutile of AES_BLOCKLEN;
69 | // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
70 | // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv()
71 | // no IV should ever be reused with the same key
72 | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
73 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
74 |
75 | #endif // #if defined(CBC) && (CBC == 1)
76 |
77 |
78 | #if defined(CTR) && (CTR == 1)
79 |
80 | // Same function for encrypting as for decrypting.
81 | // IV is incremented for every block, and used after encryption as XOR-compliment for output
82 | // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme
83 | // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv()
84 | // no IV should ever be reused with the same key
85 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, uint32_t length);
86 |
87 | #endif // #if defined(CTR) && (CTR == 1)
88 |
89 |
90 | #endif //_AES_H_
91 |
--------------------------------------------------------------------------------
/airplay/aes_ctr.c:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 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 "aes_ctr.h"
19 |
20 | static void
21 | ctr128_inc(uint8_t *counter)
22 | {
23 | uint32_t n = 16, c = 1;
24 |
25 | do {
26 | --n;
27 | c += counter[n];
28 | counter[n] = (uint8_t) c;
29 | c >>= 8;
30 | } while (n);
31 | }
32 |
33 | void
34 | AES_ctr_set_key(AES_CTR_CTX *ctx, const uint8_t *key, const uint8_t *nonce, AES_MODE mode)
35 | {
36 | assert(ctx);
37 |
38 | /* Setting IV as nonce, but it will be overridden in encrypt */
39 | AES_set_key(&ctx->aes_ctx, key, nonce, mode);
40 | memcpy(ctx->counter, nonce, AES_BLOCKSIZE);
41 | memset(ctx->state, 0, AES_BLOCKSIZE);
42 | ctx->available = 0;
43 | }
44 |
45 | void
46 | AES_ctr_encrypt(AES_CTR_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
47 | {
48 | unsigned char block[16];
49 | int msgidx, i;
50 |
51 | assert(ctx);
52 | assert(msg);
53 | assert(out);
54 |
55 | msgidx = 0;
56 | while (msgidx < length) {
57 | if (ctx->available == 0) {
58 | /* Generate a new block into state if we have no bytes */
59 | memset(ctx->aes_ctx.iv, 0, AES_IV_SIZE);
60 | AES_cbc_encrypt(&ctx->aes_ctx, ctx->counter, ctx->state, AES_BLOCKSIZE);
61 | ctx->available = AES_BLOCKSIZE;
62 | ctr128_inc(ctx->counter);
63 | }
64 | for (i=0; iavailable && msgidxstate[AES_BLOCKSIZE-ctx->available+i];
66 | }
67 | ctx->available -= i;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/airplay/aes_ctr.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 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 AES_CTR_H
16 | #define AES_CTR_H
17 | #ifdef __cplusplus
18 | extern "C" {
19 | #endif
20 | #include
21 | #include "crypto/crypto.h"
22 |
23 | typedef struct aes_ctr_key_st {
24 | AES_CTX aes_ctx;
25 | uint8_t counter[AES_BLOCKSIZE];
26 | uint8_t state[AES_BLOCKSIZE];
27 | uint8_t available;
28 | } AES_CTR_CTX;
29 |
30 | void AES_ctr_set_key(AES_CTR_CTX *ctx, const uint8_t *key, const uint8_t *nonce, AES_MODE mode);
31 | void AES_ctr_encrypt(AES_CTR_CTX *ctx, const uint8_t *msg, uint8_t *out, int length);
32 | #ifdef __cplusplus
33 | }
34 | #endif
35 | #endif
36 |
--------------------------------------------------------------------------------
/airplay/byteutils.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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 "byteutils.h"
18 |
19 | #ifndef htonll
20 | #ifdef SYS_ENDIAN_H
21 | #include
22 | #else
23 | #include
24 | #endif
25 | #define htonll(x) htobe64(x)
26 | #define ntohll(x) be64toh(x)
27 | #endif
28 |
29 | // The functions in this file assume a little endian cpu architecture!
30 |
31 | /**
32 | * Reads a little endian unsigned 16 bit integer from the buffer at position offset
33 | */
34 | uint16_t byteutils_get_short(unsigned char* b, int offset) {
35 | return *((uint16_t*)(b + offset));
36 | }
37 |
38 | /**
39 | * Reads a little endian unsigned 32 bit integer from the buffer at position offset
40 | */
41 | uint32_t byteutils_get_int(unsigned char* b, int offset) {
42 | return *((uint32_t*)(b + offset));
43 | }
44 |
45 | /**
46 | * Reads a little endian unsigned 64 bit integer from the buffer at position offset
47 | */
48 | uint64_t byteutils_get_long(unsigned char* b, int offset) {
49 | return *((uint64_t*)(b + offset));
50 | }
51 |
52 | /**
53 | * Reads a big endian unsigned 16 bit integer from the buffer at position offset
54 | */
55 | uint16_t byteutils_get_short_be(unsigned char* b, int offset) {
56 | return ntohs(byteutils_get_short(b, offset));
57 | }
58 |
59 | /**
60 | * Reads a big endian unsigned 32 bit integer from the buffer at position offset
61 | */
62 | uint32_t byteutils_get_int_be(unsigned char* b, int offset) {
63 | return ntohl(byteutils_get_int(b, offset));
64 | }
65 |
66 | /**
67 | * Reads a big endian unsigned 64 bit integer from the buffer at position offset
68 | */
69 | uint64_t byteutils_get_long_be(unsigned char* b, int offset) {
70 | return ntohll(byteutils_get_long(b, offset));
71 | }
72 |
73 | /**
74 | * Reads a float from the buffer at position offset
75 | */
76 | float byteutils_get_float(unsigned char* b, int offset) {
77 | return *((float*)(b + offset));
78 | }
79 |
80 | /**
81 | * Writes a little endian unsigned 32 bit integer to the buffer at position offset
82 | */
83 | void byteutils_put_int(unsigned char* b, int offset, uint32_t value) {
84 | *((uint32_t*)(b + offset)) = value;
85 | }
86 |
87 | /**
88 | * Reads an ntp timestamp and returns it as micro seconds since the Unix epoch
89 | */
90 | uint64_t byteutils_get_ntp_timestamp(unsigned char *b, int offset) {
91 | uint64_t seconds = ntohl(((unsigned int) byteutils_get_int(b, offset))) - SECONDS_FROM_1900_TO_1970;
92 | uint64_t fraction = ntohl((unsigned int) byteutils_get_int(b, offset + 4));
93 | return (seconds * 1000000L) + ((fraction * 1000000L) >> 32);
94 | }
95 |
96 | /**
97 | * Writes a time given as micro seconds since the Unix time epoch as an ntp timestamp
98 | * into the buffer at position offset
99 | */
100 | void byteutils_put_ntp_timestamp(unsigned char *b, int offset, uint64_t us_since_1970) {
101 | uint64_t seconds = us_since_1970 / 1000000L;
102 | uint64_t microseconds = us_since_1970 % 1000000L;
103 | seconds += SECONDS_FROM_1900_TO_1970;
104 | uint64_t fraction = (microseconds << 32) / 1000000L;
105 |
106 | // Write in big endian!
107 | byteutils_put_int(b, offset, htonl(seconds));
108 | byteutils_put_int(b, offset + 4, htonl(fraction));
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/airplay/byteutils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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 AIRPLAYSERVER_BYTEUTILS_H
16 | #define AIRPLAYSERVER_BYTEUTILS_H
17 | #include
18 |
19 | uint16_t byteutils_get_short(unsigned char* b, int offset);
20 | uint32_t byteutils_get_int(unsigned char* b, int offset);
21 | uint64_t byteutils_get_long(unsigned char* b, int offset);
22 | uint16_t byteutils_get_short_be(unsigned char* b, int offset);
23 | uint32_t byteutils_get_int_be(unsigned char* b, int offset);
24 | uint64_t byteutils_get_long_be(unsigned char* b, int offset);
25 | float byteutils_get_float(unsigned char* b, int offset);
26 |
27 | #define SECONDS_FROM_1900_TO_1970 2208988800ULL
28 |
29 | uint64_t byteutils_get_ntp_timestamp(unsigned char *b, int offset);
30 | void byteutils_put_ntp_timestamp(unsigned char *b, int offset, uint64_t us_since_1970);
31 |
32 | #endif //AIRPLAYSERVER_BYTEUTILS_H
33 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/crypto/crypto.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 crypto.h
33 | */
34 |
35 | #ifndef HEADER_CRYPTO_H
36 | #define HEADER_CRYPTO_H
37 |
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 |
42 | #include "config.h"
43 | #include "bigint_impl.h"
44 | #include "bigint.h"
45 |
46 | #ifndef STDCALL
47 | #define STDCALL
48 | #endif
49 | #ifndef EXP_FUNC
50 | #define EXP_FUNC
51 | #endif
52 |
53 | /**************************************************************************
54 | * AES declarations
55 | **************************************************************************/
56 |
57 | #define AES_MAXROUNDS 14
58 | #define AES_BLOCKSIZE 16
59 | #define AES_IV_SIZE 16
60 |
61 | typedef struct aes_key_st
62 | {
63 | uint16_t rounds;
64 | uint16_t key_size;
65 | uint32_t ks[(AES_MAXROUNDS+1)*8];
66 | uint8_t iv[AES_IV_SIZE];
67 | } AES_CTX;
68 |
69 | typedef enum
70 | {
71 | AES_MODE_128,
72 | AES_MODE_256
73 | } AES_MODE;
74 |
75 | void AES_set_key(AES_CTX *ctx, const uint8_t *key,
76 | const uint8_t *iv, AES_MODE mode);
77 | void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg,
78 | uint8_t *out, int length);
79 | void AES_cbc_decrypt(AES_CTX *ks, const uint8_t *in, uint8_t *out, int length);
80 | void AES_convert_key(AES_CTX *ctx);
81 |
82 | /**************************************************************************
83 | * RC4 declarations
84 | **************************************************************************/
85 |
86 | typedef struct
87 | {
88 | uint8_t x, y, m[256];
89 | } RC4_CTX;
90 |
91 | void RC4_setup(RC4_CTX *s, const uint8_t *key, int length);
92 | void RC4_crypt(RC4_CTX *s, const uint8_t *msg, uint8_t *data, int length);
93 |
94 | /**************************************************************************
95 | * SHA1 declarations
96 | **************************************************************************/
97 |
98 | #define SHA1_SIZE 20
99 |
100 | /*
101 | * This structure will hold context information for the SHA-1
102 | * hashing operation
103 | */
104 | typedef struct
105 | {
106 | uint32_t Intermediate_Hash[SHA1_SIZE/4]; /* Message Digest */
107 | uint32_t Length_Low; /* Message length in bits */
108 | uint32_t Length_High; /* Message length in bits */
109 | uint16_t Message_Block_Index; /* Index into message block array */
110 | uint8_t Message_Block[64]; /* 512-bit message blocks */
111 | } SHA1_CTX;
112 |
113 | void SHA1_Init(SHA1_CTX *);
114 | void SHA1_Update(SHA1_CTX *, const uint8_t * msg, int len);
115 | void SHA1_Final(uint8_t *digest, SHA1_CTX *);
116 |
117 | /**************************************************************************
118 | * MD5 declarations
119 | **************************************************************************/
120 |
121 | #define MD5_SIZE 16
122 |
123 | typedef struct
124 | {
125 | uint32_t state[4]; /* state (ABCD) */
126 | uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */
127 | uint8_t buffer[64]; /* input buffer */
128 | } MD5_CTX;
129 |
130 | EXP_FUNC void STDCALL MD5_Init(MD5_CTX *);
131 | EXP_FUNC void STDCALL MD5_Update(MD5_CTX *, const uint8_t *msg, int len);
132 | EXP_FUNC void STDCALL MD5_Final(uint8_t *digest, MD5_CTX *);
133 |
134 | /**************************************************************************
135 | * HMAC declarations
136 | **************************************************************************/
137 | void hmac_md5(const uint8_t *msg, int length, const uint8_t *key,
138 | int key_len, uint8_t *digest);
139 | void hmac_sha1(const uint8_t *msg, int length, const uint8_t *key,
140 | int key_len, uint8_t *digest);
141 |
142 | #ifdef __cplusplus
143 | }
144 | #endif
145 |
146 | #endif
147 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/curve25519/curve25519.h:
--------------------------------------------------------------------------------
1 | #ifndef CURVE25519_DONNA_H
2 | #define CURVE25519_DONNA_H
3 |
4 | static const unsigned char kCurve25519BasePoint[32] = { 9 };
5 |
6 | int curve25519_donna(unsigned char *mypublic, const unsigned char *secret, const unsigned char *basepoint);
7 |
8 | #endif
9 |
--------------------------------------------------------------------------------
/airplay/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(const char *name, int name_len, const char *hw_addr, int hw_addr_len, int *error);
23 |
24 | DNSSD_API int dnssd_register_raop(dnssd_t *dnssd, unsigned short port);
25 | DNSSD_API int dnssd_register_airplay(dnssd_t *dnssd, unsigned short port);
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 const char *dnssd_get_airplay_txt(dnssd_t *dnssd, int *length);
31 | DNSSD_API const char *dnssd_get_name(dnssd_t *dnssd, int *length);
32 | DNSSD_API const char *dnssd_get_hw_addr(dnssd_t *dnssd, int *length);
33 |
34 | DNSSD_API void dnssd_destroy(dnssd_t *dnssd);
35 |
36 | #ifdef __cplusplus
37 | }
38 | #endif
39 | #endif
--------------------------------------------------------------------------------
/airplay/dnssdint.h:
--------------------------------------------------------------------------------
1 | #ifndef DNSSDINT_H
2 | #define DNSSDINT_H
3 |
4 | #include "global.h"
5 | #define RAOP_TXTVERS "1"
6 | #define RAOP_CH "2" /* Audio channels: 2 */
7 | #define RAOP_CN "0,1,2,3" /* Audio codec: PCM, ALAC, AAC, AAC ELD */
8 | #define RAOP_ET "0,3,5" /* Encryption type: None, FairPlay, FairPlay SAPv2.5 */
9 | #define RAOP_VV "2"
10 | #define RAOP_FT "0x5A7FFEE6"
11 | #define RAOP_RHD "5.6.0.0"
12 | #define RAOP_SF "0x4"
13 | #define RAOP_SV "false"
14 | #define RAOP_DA "true"
15 | #define RAOP_SR "44100" /* Sample rate: 44100 */
16 | #define RAOP_SS "16" /* Sample size: 16 */
17 | #define RAOP_VS GLOBAL_VERSION /* defined in global.h */
18 | #define RAOP_TP "UDP" /* Transport protocol. Possible values: UDP or TCP or TCP,UDP */
19 | #define RAOP_MD "0,1,2" /* Metadata: text, artwork, progress */
20 | #define RAOP_VN "65537"
21 | #define RAOP_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
22 |
23 | #define AIRPLAY_FEATURES "0x5A7FFEE6"
24 | #define AIRPLAY_SRCVERS GLOBAL_VERSION /*defined in global.h */
25 | #define AIRPLAY_FLAGS "0x4"
26 | #define AIRPLAY_VV "2"
27 | #define AIRPLAY_PK "b07727d6f6cd6e08b58ede525ec3cdeaa252ad9f683feb212ef8a205246554e7"
28 | #define AIRPLAY_PI "2e388006-13ba-4041-9a67-25dd4a43d536"
29 |
30 | #endif
31 |
--------------------------------------------------------------------------------
/airplay/ed25519/add_scalar.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 | #include "ge.h"
3 | #include "sc.h"
4 | #include "sha512.h"
5 |
6 |
7 | /* see http://crypto.stackexchange.com/a/6215/4697 */
8 | void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar) {
9 | const unsigned char SC_1[32] = {1}; /* scalar with value 1 */
10 |
11 | unsigned char n[32];
12 | ge_p3 nB;
13 | ge_p1p1 A_p1p1;
14 | ge_p3 A;
15 | ge_p3 public_key_unpacked;
16 | ge_cached T;
17 |
18 | sha512_context hash;
19 | unsigned char hashbuf[64];
20 |
21 | int i;
22 |
23 | /* copy the scalar and clear highest bit */
24 | for (i = 0; i < 31; ++i) {
25 | n[i] = scalar[i];
26 | }
27 | n[31] = scalar[31] & 127;
28 |
29 | /* private key: a = n + t */
30 | if (private_key) {
31 | sc_muladd(private_key, SC_1, n, private_key);
32 |
33 | // https://github.com/orlp/ed25519/issues/3
34 | sha512_init(&hash);
35 | sha512_update(&hash, private_key + 32, 32);
36 | sha512_update(&hash, scalar, 32);
37 | sha512_final(&hash, hashbuf);
38 | for (i = 0; i < 32; ++i) {
39 | private_key[32 + i] = hashbuf[i];
40 | }
41 | }
42 |
43 | /* public key: A = nB + T */
44 | if (public_key) {
45 | /* if we know the private key we don't need a point addition, which is faster */
46 | /* using a "timing attack" you could find out wether or not we know the private
47 | key, but this information seems rather useless - if this is important pass
48 | public_key and private_key seperately in 2 function calls */
49 | if (private_key) {
50 | ge_scalarmult_base(&A, private_key);
51 | } else {
52 | /* unpack public key into T */
53 | ge_frombytes_negate_vartime(&public_key_unpacked, public_key);
54 | fe_neg(public_key_unpacked.X, public_key_unpacked.X); /* undo negate */
55 | fe_neg(public_key_unpacked.T, public_key_unpacked.T); /* undo negate */
56 | ge_p3_to_cached(&T, &public_key_unpacked);
57 |
58 | /* calculate n*B */
59 | ge_scalarmult_base(&nB, n);
60 |
61 | /* A = n*B + T */
62 | ge_add(&A_p1p1, &nB, &T);
63 | ge_p1p1_to_p3(&A, &A_p1p1);
64 | }
65 |
66 | /* pack public key */
67 | ge_p3_tobytes(public_key, &A);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/airplay/ed25519/ed25519.h:
--------------------------------------------------------------------------------
1 | #ifndef ED25519_H
2 | #define ED25519_H
3 |
4 | #include
5 |
6 | #if defined(_WIN32)
7 | #if defined(ED25519_BUILD_DLL)
8 | #define ED25519_DECLSPEC __declspec(dllexport)
9 | #elif defined(ED25519_DLL)
10 | #define ED25519_DECLSPEC __declspec(dllimport)
11 | #else
12 | #define ED25519_DECLSPEC
13 | #endif
14 | #else
15 | #define ED25519_DECLSPEC
16 | #endif
17 |
18 |
19 | #ifdef __cplusplus
20 | extern "C" {
21 | #endif
22 |
23 | #ifndef ED25519_NO_SEED
24 | int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed);
25 | #endif
26 |
27 | void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
28 | void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
29 | int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key);
30 | void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
31 | void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
32 |
33 |
34 | #ifdef __cplusplus
35 | }
36 | #endif
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/airplay/ed25519/fe.h:
--------------------------------------------------------------------------------
1 | #ifndef FE_H
2 | #define FE_H
3 |
4 | #include "fixedint.h"
5 |
6 |
7 | /*
8 | fe means field element.
9 | Here the field is \Z/(2^255-19).
10 | An element t, entries t[0]...t[9], represents the integer
11 | t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9].
12 | Bounds on each t[i] vary depending on context.
13 | */
14 |
15 |
16 | typedef int32_t fe[10];
17 |
18 |
19 | void fe_0(fe h);
20 | void fe_1(fe h);
21 |
22 | void fe_frombytes(fe h, const unsigned char *s);
23 | void fe_tobytes(unsigned char *s, const fe h);
24 |
25 | void fe_copy(fe h, const fe f);
26 | int fe_isnegative(const fe f);
27 | int fe_isnonzero(const fe f);
28 | void fe_cmov(fe f, const fe g, unsigned int b);
29 | void fe_cswap(fe f, fe g, unsigned int b);
30 |
31 | void fe_neg(fe h, const fe f);
32 | void fe_add(fe h, const fe f, const fe g);
33 | void fe_invert(fe out, const fe z);
34 | void fe_sq(fe h, const fe f);
35 | void fe_sq2(fe h, const fe f);
36 | void fe_mul(fe h, const fe f, const fe g);
37 | void fe_mul121666(fe h, fe f);
38 | void fe_pow22523(fe out, const fe z);
39 | void fe_sub(fe h, const fe f, const fe g);
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/airplay/ed25519/fixedint.h:
--------------------------------------------------------------------------------
1 | /*
2 | Portable header to provide the 32 and 64 bits type.
3 |
4 | Not a compatible replacement for , do not blindly use it as such.
5 | */
6 |
7 | #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__WATCOMC__) && (defined(_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_) || defined(__UINT_FAST64_TYPE__)) )) && !defined(FIXEDINT_H_INCLUDED)
8 | #include
9 | #define FIXEDINT_H_INCLUDED
10 |
11 | #if defined(__WATCOMC__) && __WATCOMC__ >= 1250 && !defined(UINT64_C)
12 | #include
13 | #define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
14 | #endif
15 | #endif
16 |
17 |
18 | #ifndef FIXEDINT_H_INCLUDED
19 | #define FIXEDINT_H_INCLUDED
20 |
21 | #include
22 |
23 | /* (u)int32_t */
24 | #ifndef uint32_t
25 | #if (ULONG_MAX == 0xffffffffUL)
26 | typedef unsigned long uint32_t;
27 | #elif (UINT_MAX == 0xffffffffUL)
28 | typedef unsigned int uint32_t;
29 | #elif (USHRT_MAX == 0xffffffffUL)
30 | typedef unsigned short uint32_t;
31 | #endif
32 | #endif
33 |
34 |
35 | #ifndef int32_t
36 | #if (LONG_MAX == 0x7fffffffL)
37 | typedef signed long int32_t;
38 | #elif (INT_MAX == 0x7fffffffL)
39 | typedef signed int int32_t;
40 | #elif (SHRT_MAX == 0x7fffffffL)
41 | typedef signed short int32_t;
42 | #endif
43 | #endif
44 |
45 |
46 | /* (u)int64_t */
47 | #if (defined(__STDC__) && defined(__STDC_VERSION__) && __STDC__ && __STDC_VERSION__ >= 199901L)
48 | typedef long long int64_t;
49 | typedef unsigned long long uint64_t;
50 |
51 | #define UINT64_C(v) v ##ULL
52 | #define INT64_C(v) v ##LL
53 | #elif defined(__GNUC__)
54 | __extension__ typedef long long int64_t;
55 | __extension__ typedef unsigned long long uint64_t;
56 |
57 | #define UINT64_C(v) v ##ULL
58 | #define INT64_C(v) v ##LL
59 | #elif defined(__MWERKS__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) || defined(__APPLE_CC__) || defined(_LONG_LONG) || defined(_CRAYC)
60 | typedef long long int64_t;
61 | typedef unsigned long long uint64_t;
62 |
63 | #define UINT64_C(v) v ##ULL
64 | #define INT64_C(v) v ##LL
65 | #elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined(__BORLANDC__) && __BORLANDC__ > 0x460) || defined(__alpha) || defined(__DECC)
66 | typedef __int64 int64_t;
67 | typedef unsigned __int64 uint64_t;
68 |
69 | #define UINT64_C(v) v ##UI64
70 | #define INT64_C(v) v ##I64
71 | #endif
72 | #endif
73 |
--------------------------------------------------------------------------------
/airplay/ed25519/ge.h:
--------------------------------------------------------------------------------
1 | #ifndef GE_H
2 | #define GE_H
3 |
4 | #include "fe.h"
5 |
6 |
7 | /*
8 | ge means group element.
9 |
10 | Here the group is the set of pairs (x,y) of field elements (see fe.h)
11 | satisfying -x^2 + y^2 = 1 + d x^2y^2
12 | where d = -121665/121666.
13 |
14 | Representations:
15 | ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
16 | ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
17 | ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
18 | ge_precomp (Duif): (y+x,y-x,2dxy)
19 | */
20 |
21 | typedef struct {
22 | fe X;
23 | fe Y;
24 | fe Z;
25 | } ge_p2;
26 |
27 | typedef struct {
28 | fe X;
29 | fe Y;
30 | fe Z;
31 | fe T;
32 | } ge_p3;
33 |
34 | typedef struct {
35 | fe X;
36 | fe Y;
37 | fe Z;
38 | fe T;
39 | } ge_p1p1;
40 |
41 | typedef struct {
42 | fe yplusx;
43 | fe yminusx;
44 | fe xy2d;
45 | } ge_precomp;
46 |
47 | typedef struct {
48 | fe YplusX;
49 | fe YminusX;
50 | fe Z;
51 | fe T2d;
52 | } ge_cached;
53 |
54 | void ge_p3_tobytes(unsigned char *s, const ge_p3 *h);
55 | void ge_tobytes(unsigned char *s, const ge_p2 *h);
56 | int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s);
57 |
58 | void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
59 | void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
60 | void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
61 | void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
62 | void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
63 | void ge_scalarmult_base(ge_p3 *h, const unsigned char *a);
64 |
65 | void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
66 | void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
67 | void ge_p2_0(ge_p2 *h);
68 | void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p);
69 | void ge_p3_0(ge_p3 *h);
70 | void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p);
71 | void ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
72 | void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p);
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/airplay/ed25519/key_exchange.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 | #include "fe.h"
3 |
4 | void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key) {
5 | unsigned char e[32];
6 | unsigned int i;
7 |
8 | fe x1;
9 | fe x2;
10 | fe z2;
11 | fe x3;
12 | fe z3;
13 | fe tmp0;
14 | fe tmp1;
15 |
16 | int pos;
17 | unsigned int swap;
18 | unsigned int b;
19 |
20 | /* copy the private key and make sure it's valid */
21 | for (i = 0; i < 32; ++i) {
22 | e[i] = private_key[i];
23 | }
24 |
25 | e[0] &= 248;
26 | e[31] &= 63;
27 | e[31] |= 64;
28 |
29 | /* unpack the public key and convert edwards to montgomery */
30 | /* due to CodesInChaos: montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p */
31 | fe_frombytes(x1, public_key);
32 | fe_1(tmp1);
33 | fe_add(tmp0, x1, tmp1);
34 | fe_sub(tmp1, tmp1, x1);
35 | fe_invert(tmp1, tmp1);
36 | fe_mul(x1, tmp0, tmp1);
37 |
38 | fe_1(x2);
39 | fe_0(z2);
40 | fe_copy(x3, x1);
41 | fe_1(z3);
42 |
43 | swap = 0;
44 | for (pos = 254; pos >= 0; --pos) {
45 | b = e[pos / 8] >> (pos & 7);
46 | b &= 1;
47 | swap ^= b;
48 | fe_cswap(x2, x3, swap);
49 | fe_cswap(z2, z3, swap);
50 | swap = b;
51 |
52 | /* from montgomery.h */
53 | fe_sub(tmp0, x3, z3);
54 | fe_sub(tmp1, x2, z2);
55 | fe_add(x2, x2, z2);
56 | fe_add(z2, x3, z3);
57 | fe_mul(z3, tmp0, x2);
58 | fe_mul(z2, z2, tmp1);
59 | fe_sq(tmp0, tmp1);
60 | fe_sq(tmp1, x2);
61 | fe_add(x3, z3, z2);
62 | fe_sub(z2, z3, z2);
63 | fe_mul(x2, tmp1, tmp0);
64 | fe_sub(tmp1, tmp1, tmp0);
65 | fe_sq(z2, z2);
66 | fe_mul121666(z3, tmp1);
67 | fe_sq(x3, x3);
68 | fe_add(tmp0, tmp0, z3);
69 | fe_mul(z3, x1, z2);
70 | fe_mul(z2, tmp1, tmp0);
71 | }
72 |
73 | fe_cswap(x2, x3, swap);
74 | fe_cswap(z2, z3, swap);
75 |
76 | fe_invert(z2, z2);
77 | fe_mul(x2, x2, z2);
78 | fe_tobytes(shared_secret, x2);
79 | }
80 |
--------------------------------------------------------------------------------
/airplay/ed25519/keypair.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 | #include "sha512.h"
3 | #include "ge.h"
4 |
5 |
6 | void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed) {
7 | ge_p3 A;
8 |
9 | sha512(seed, 32, private_key);
10 | private_key[0] &= 248;
11 | private_key[31] &= 63;
12 | private_key[31] |= 64;
13 |
14 | ge_scalarmult_base(&A, private_key);
15 | ge_p3_tobytes(public_key, &A);
16 | }
17 |
--------------------------------------------------------------------------------
/airplay/ed25519/sc.h:
--------------------------------------------------------------------------------
1 | #ifndef SC_H
2 | #define SC_H
3 |
4 | /*
5 | The set of scalars is \Z/l
6 | where l = 2^252 + 27742317777372353535851937790883648493.
7 | */
8 |
9 | void sc_reduce(unsigned char *s);
10 | void sc_muladd(unsigned char *s, const unsigned char *a, const unsigned char *b, const unsigned char *c);
11 |
12 | #endif
13 |
--------------------------------------------------------------------------------
/airplay/ed25519/seed.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 |
3 | #ifndef ED25519_NO_SEED
4 |
5 | #ifdef _WIN32
6 | #include
7 | #include
8 | #else
9 | #include
10 | #endif
11 |
12 | int ed25519_create_seed(unsigned char *seed) {
13 | #ifdef _WIN32
14 | HCRYPTPROV prov;
15 |
16 | if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
17 | return 1;
18 | }
19 |
20 | if (!CryptGenRandom(prov, 32, seed)) {
21 | CryptReleaseContext(prov, 0);
22 | return 1;
23 | }
24 |
25 | CryptReleaseContext(prov, 0);
26 | #else
27 | FILE *f = fopen("/dev/urandom", "rb");
28 |
29 | if (f == NULL) {
30 | return 1;
31 | }
32 |
33 | fread(seed, 1, 32, f);
34 | fclose(f);
35 | #endif
36 |
37 | return 0;
38 | }
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/airplay/ed25519/sha512.h:
--------------------------------------------------------------------------------
1 | #ifndef SHA512_H
2 | #define SHA512_H
3 |
4 | #include
5 |
6 | #include "fixedint.h"
7 |
8 | /* state */
9 | typedef struct sha512_context_ {
10 | uint64_t length, state[8];
11 | size_t curlen;
12 | unsigned char buf[128];
13 | } sha512_context;
14 |
15 | #ifdef __cplusplus
16 | extern "C" {
17 | #endif
18 |
19 | int sha512_init(sha512_context * md);
20 | int sha512_final(sha512_context * md, unsigned char *out);
21 | int sha512_update(sha512_context * md, const unsigned char *in, size_t inlen);
22 | int sha512(const unsigned char *message, size_t message_len, unsigned char *out);
23 | #ifdef __cplusplus
24 | }
25 | #endif
26 |
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/airplay/ed25519/sign.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 | #include "sha512.h"
3 | #include "ge.h"
4 | #include "sc.h"
5 |
6 |
7 | void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key) {
8 | sha512_context hash;
9 | unsigned char hram[64];
10 | unsigned char r[64];
11 | ge_p3 R;
12 |
13 |
14 | sha512_init(&hash);
15 | sha512_update(&hash, private_key + 32, 32);
16 | sha512_update(&hash, message, message_len);
17 | sha512_final(&hash, r);
18 |
19 | sc_reduce(r);
20 | ge_scalarmult_base(&R, r);
21 | ge_p3_tobytes(signature, &R);
22 |
23 | sha512_init(&hash);
24 | sha512_update(&hash, signature, 32);
25 | sha512_update(&hash, public_key, 32);
26 | sha512_update(&hash, message, message_len);
27 | sha512_final(&hash, hram);
28 |
29 | sc_reduce(hram);
30 | sc_muladd(signature + 32, hram, private_key, r);
31 | }
32 |
--------------------------------------------------------------------------------
/airplay/ed25519/verify.c:
--------------------------------------------------------------------------------
1 | #include "ed25519.h"
2 | #include "sha512.h"
3 | #include "ge.h"
4 | #include "sc.h"
5 |
6 | static int consttime_equal(const unsigned char *x, const unsigned char *y) {
7 | unsigned char r = 0;
8 |
9 | r = x[0] ^ y[0];
10 | #define F(i) r |= x[i] ^ y[i]
11 | F(1);
12 | F(2);
13 | F(3);
14 | F(4);
15 | F(5);
16 | F(6);
17 | F(7);
18 | F(8);
19 | F(9);
20 | F(10);
21 | F(11);
22 | F(12);
23 | F(13);
24 | F(14);
25 | F(15);
26 | F(16);
27 | F(17);
28 | F(18);
29 | F(19);
30 | F(20);
31 | F(21);
32 | F(22);
33 | F(23);
34 | F(24);
35 | F(25);
36 | F(26);
37 | F(27);
38 | F(28);
39 | F(29);
40 | F(30);
41 | F(31);
42 | #undef F
43 |
44 | return !r;
45 | }
46 |
47 | int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key) {
48 | unsigned char h[64];
49 | unsigned char checker[32];
50 | sha512_context hash;
51 | ge_p3 A;
52 | ge_p2 R;
53 |
54 | if (signature[63] & 224) {
55 | return 0;
56 | }
57 |
58 | if (ge_frombytes_negate_vartime(&A, public_key) != 0) {
59 | return 0;
60 | }
61 |
62 | sha512_init(&hash);
63 | sha512_update(&hash, signature, 32);
64 | sha512_update(&hash, public_key, 32);
65 | sha512_update(&hash, message, message_len);
66 | sha512_final(&hash, h);
67 |
68 | sc_reduce(h);
69 | ge_double_scalarmult_vartime(&R, h, &A, signature + 32);
70 | ge_tobytes(checker, &R);
71 |
72 | if (!consttime_equal(checker, signature)) {
73 | return 0;
74 | }
75 |
76 | return 1;
77 | }
78 |
--------------------------------------------------------------------------------
/airplay/fairplay.h:
--------------------------------------------------------------------------------
1 | #ifndef FAIRPLAY_H
2 | #define FAIRPLAY_H
3 |
4 | #include "logger.h"
5 |
6 | typedef struct fairplay_s fairplay_t;
7 |
8 | fairplay_t *fairplay_init(logger_t *logger);
9 | int fairplay_setup(fairplay_t *fp, const unsigned char req[16], unsigned char res[142]);
10 | int fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char res[32]);
11 | int fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16]);
12 | void fairplay_destroy(fairplay_t *fp);
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/airplay/fairplay_playfair.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "fairplay.h"
6 | #include "playfair/playfair.h"
7 |
8 | char reply_message[4][142] = {{0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x00,0x0f,0x9f,0x3f,0x9e,0x0a,0x25,0x21,0xdb,0xdf,0x31,0x2a,0xb2,0xbf,0xb2,0x9e,0x8d,0x23,0x2b,0x63,0x76,0xa8,0xc8,0x18,0x70,0x1d,0x22,0xae,0x93,0xd8,0x27,0x37,0xfe,0xaf,0x9d,0xb4,0xfd,0xf4,0x1c,0x2d,0xba,0x9d,0x1f,0x49,0xca,0xaa,0xbf,0x65,0x91,0xac,0x1f,0x7b,0xc6,0xf7,0xe0,0x66,0x3d,0x21,0xaf,0xe0,0x15,0x65,0x95,0x3e,0xab,0x81,0xf4,0x18,0xce,0xed,0x09,0x5a,0xdb,0x7c,0x3d,0x0e,0x25,0x49,0x09,0xa7,0x98,0x31,0xd4,0x9c,0x39,0x82,0x97,0x34,0x34,0xfa,0xcb,0x42,0xc6,0x3a,0x1c,0xd9,0x11,0xa6,0xfe,0x94,0x1a,0x8a,0x6d,0x4a,0x74,0x3b,0x46,0xc3,0xa7,0x64,0x9e,0x44,0xc7,0x89,0x55,0xe4,0x9d,0x81,0x55,0x00,0x95,0x49,0xc4,0xe2,0xf7,0xa3,0xf6,0xd5,0xba},
9 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x01,0xcf,0x32,0xa2,0x57,0x14,0xb2,0x52,0x4f,0x8a,0xa0,0xad,0x7a,0xf1,0x64,0xe3,0x7b,0xcf,0x44,0x24,0xe2,0x00,0x04,0x7e,0xfc,0x0a,0xd6,0x7a,0xfc,0xd9,0x5d,0xed,0x1c,0x27,0x30,0xbb,0x59,0x1b,0x96,0x2e,0xd6,0x3a,0x9c,0x4d,0xed,0x88,0xba,0x8f,0xc7,0x8d,0xe6,0x4d,0x91,0xcc,0xfd,0x5c,0x7b,0x56,0xda,0x88,0xe3,0x1f,0x5c,0xce,0xaf,0xc7,0x43,0x19,0x95,0xa0,0x16,0x65,0xa5,0x4e,0x19,0x39,0xd2,0x5b,0x94,0xdb,0x64,0xb9,0xe4,0x5d,0x8d,0x06,0x3e,0x1e,0x6a,0xf0,0x7e,0x96,0x56,0x16,0x2b,0x0e,0xfa,0x40,0x42,0x75,0xea,0x5a,0x44,0xd9,0x59,0x1c,0x72,0x56,0xb9,0xfb,0xe6,0x51,0x38,0x98,0xb8,0x02,0x27,0x72,0x19,0x88,0x57,0x16,0x50,0x94,0x2a,0xd9,0x46,0x68,0x8a},
10 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x02,0xc1,0x69,0xa3,0x52,0xee,0xed,0x35,0xb1,0x8c,0xdd,0x9c,0x58,0xd6,0x4f,0x16,0xc1,0x51,0x9a,0x89,0xeb,0x53,0x17,0xbd,0x0d,0x43,0x36,0xcd,0x68,0xf6,0x38,0xff,0x9d,0x01,0x6a,0x5b,0x52,0xb7,0xfa,0x92,0x16,0xb2,0xb6,0x54,0x82,0xc7,0x84,0x44,0x11,0x81,0x21,0xa2,0xc7,0xfe,0xd8,0x3d,0xb7,0x11,0x9e,0x91,0x82,0xaa,0xd7,0xd1,0x8c,0x70,0x63,0xe2,0xa4,0x57,0x55,0x59,0x10,0xaf,0x9e,0x0e,0xfc,0x76,0x34,0x7d,0x16,0x40,0x43,0x80,0x7f,0x58,0x1e,0xe4,0xfb,0xe4,0x2c,0xa9,0xde,0xdc,0x1b,0x5e,0xb2,0xa3,0xaa,0x3d,0x2e,0xcd,0x59,0xe7,0xee,0xe7,0x0b,0x36,0x29,0xf2,0x2a,0xfd,0x16,0x1d,0x87,0x73,0x53,0xdd,0xb9,0x9a,0xdc,0x8e,0x07,0x00,0x6e,0x56,0xf8,0x50,0xce},
11 | {0x46,0x50,0x4c,0x59,0x03,0x01,0x02,0x00,0x00,0x00,0x00,0x82,0x02,0x03,0x90,0x01,0xe1,0x72,0x7e,0x0f,0x57,0xf9,0xf5,0x88,0x0d,0xb1,0x04,0xa6,0x25,0x7a,0x23,0xf5,0xcf,0xff,0x1a,0xbb,0xe1,0xe9,0x30,0x45,0x25,0x1a,0xfb,0x97,0xeb,0x9f,0xc0,0x01,0x1e,0xbe,0x0f,0x3a,0x81,0xdf,0x5b,0x69,0x1d,0x76,0xac,0xb2,0xf7,0xa5,0xc7,0x08,0xe3,0xd3,0x28,0xf5,0x6b,0xb3,0x9d,0xbd,0xe5,0xf2,0x9c,0x8a,0x17,0xf4,0x81,0x48,0x7e,0x3a,0xe8,0x63,0xc6,0x78,0x32,0x54,0x22,0xe6,0xf7,0x8e,0x16,0x6d,0x18,0xaa,0x7f,0xd6,0x36,0x25,0x8b,0xce,0x28,0x72,0x6f,0x66,0x1f,0x73,0x88,0x93,0xce,0x44,0x31,0x1e,0x4b,0xe6,0xc0,0x53,0x51,0x93,0xe5,0xef,0x72,0xe8,0x68,0x62,0x33,0x72,0x9c,0x22,0x7d,0x82,0x0c,0x99,0x94,0x45,0xd8,0x92,0x46,0xc8,0xc3,0x59}};
12 |
13 | char fp_header[] = {0x46, 0x50, 0x4c, 0x59, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x14};
14 |
15 | struct fairplay_s {
16 | logger_t *logger;
17 |
18 | unsigned char keymsg[164];
19 | unsigned int keymsglen;
20 | };
21 |
22 | fairplay_t *
23 | fairplay_init(logger_t *logger)
24 | {
25 | fairplay_t *fp;
26 |
27 | fp = calloc(1, sizeof(fairplay_t));
28 | if (!fp) {
29 | return NULL;
30 | }
31 | fp->logger = logger;
32 |
33 | return fp;
34 | }
35 |
36 | int
37 | fairplay_setup(fairplay_t *fp, const unsigned char req[16], unsigned char res[142])
38 | {
39 | int mode;
40 |
41 | assert(fp);
42 |
43 | if (req[4] != 0x03) {
44 | /* Unsupported fairplay version */
45 | return -1;
46 | }
47 |
48 | mode = req[14];
49 | memcpy(res, reply_message[mode], 142);
50 | fp->keymsglen = 0;
51 | return 0;
52 | }
53 |
54 | int
55 | fairplay_handshake(fairplay_t *fp, const unsigned char req[164], unsigned char res[32])
56 | {
57 | assert(fp);
58 |
59 | if (req[4] != 0x03) {
60 | /* Unsupported fairplay version */
61 | return -1;
62 | }
63 |
64 | memcpy(fp->keymsg, req, 164);
65 | fp->keymsglen = 164;
66 |
67 | memcpy(res, fp_header, 12);
68 | memcpy(res + 12, req + 144, 20);
69 | return 0;
70 | }
71 |
72 | int
73 | fairplay_decrypt(fairplay_t *fp, const unsigned char input[72], unsigned char output[16])
74 | {
75 | if (fp->keymsglen != 164) {
76 | return -1;
77 | }
78 |
79 | playfair_decrypt(fp->keymsg, (unsigned char *) input, output);
80 | return 0;
81 | }
82 |
83 | void
84 | fairplay_destroy(fairplay_t *fp)
85 | {
86 | free(fp);
87 | }
88 |
--------------------------------------------------------------------------------
/airplay/global.h:
--------------------------------------------------------------------------------
1 | #ifndef GLOBAL_H
2 | #define GLOBAL_H
3 |
4 | #define GLOBAL_MODEL "AppleTV3,2"
5 | #define GLOBAL_VERSION "220.68"
6 |
7 | /* use old protocol for audio AES key if client's User-Agent string is contained in these strings */
8 | /* replace xxx by any new User-Agent string as needed */
9 | #define OLD_PROTOCOL_CLIENT_USER_AGENT_LIST "AirMyPC/2.0;xxx"
10 |
11 | #define DECRYPTION_TEST 0 /* set to 1 or 2 to examine audio decryption */
12 |
13 | #define MAX_HWADDR_LEN 6
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/airplay/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 | int http_request_get_header_string(http_request_t *request, char **header_str);
34 |
35 | void http_request_destroy(http_request_t *request);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/airplay/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 | }
53 |
54 | http_response_t *
55 | http_response_init(const char *protocol, int code, const char *message)
56 | {
57 | http_response_t *response;
58 | char codestr[4];
59 |
60 | assert(code >= 100 && code < 1000);
61 |
62 | /* Convert code into string */
63 | memset(codestr, 0, sizeof(codestr));
64 | snprintf(codestr, sizeof(codestr), "%u", code);
65 |
66 | response = calloc(1, sizeof(http_response_t));
67 | if (!response) {
68 | return NULL;
69 | }
70 |
71 | /* Allocate response data */
72 | response->data_size = 1024;
73 | response->data = malloc(response->data_size);
74 | if (!response->data) {
75 | free(response);
76 | return NULL;
77 | }
78 |
79 | /* Add first line of response to the data array */
80 | http_response_add_data(response, protocol, strlen(protocol));
81 | http_response_add_data(response, " ", 1);
82 | http_response_add_data(response, codestr, strlen(codestr));
83 | http_response_add_data(response, " ", 1);
84 | http_response_add_data(response, message, strlen(message));
85 | http_response_add_data(response, "\r\n", 2);
86 |
87 | return response;
88 | }
89 |
90 | void
91 | http_response_destroy(http_response_t *response)
92 | {
93 | if (response) {
94 | free(response->data);
95 | free(response);
96 | }
97 | }
98 |
99 | void
100 | http_response_add_header(http_response_t *response, const char *name, const char *value)
101 | {
102 | assert(response);
103 | assert(name);
104 | assert(value);
105 |
106 | http_response_add_data(response, name, strlen(name));
107 | http_response_add_data(response, ": ", 2);
108 | http_response_add_data(response, value, strlen(value));
109 | http_response_add_data(response, "\r\n", 2);
110 | }
111 |
112 | void
113 | http_response_finish(http_response_t *response, const char *data, int datalen)
114 | {
115 | assert(response);
116 | assert(datalen==0 || (data && datalen > 0));
117 |
118 | if (data && datalen > 0) {
119 | const char *hdrname = "Content-Length";
120 | char hdrvalue[16];
121 |
122 | memset(hdrvalue, 0, sizeof(hdrvalue));
123 | snprintf(hdrvalue, sizeof(hdrvalue)-1, "%d", datalen);
124 |
125 | /* Add Content-Length header first */
126 | http_response_add_data(response, hdrname, strlen(hdrname));
127 | http_response_add_data(response, ": ", 2);
128 | http_response_add_data(response, hdrvalue, strlen(hdrvalue));
129 | http_response_add_data(response, "\r\n\r\n", 4);
130 |
131 | /* Add data to the end of response */
132 | http_response_add_data(response, data, datalen);
133 | } else {
134 | /* Add extra end of line after headers */
135 | http_response_add_data(response, "\r\n", 2);
136 | }
137 | response->complete = 1;
138 | }
139 |
140 | void
141 | http_response_set_disconnect(http_response_t *response, int disconnect)
142 | {
143 | assert(response);
144 |
145 | response->disconnect = !!disconnect;
146 | }
147 |
148 | int
149 | http_response_get_disconnect(http_response_t *response)
150 | {
151 | assert(response);
152 |
153 | return response->disconnect;
154 | }
155 |
156 | const char *
157 | http_response_get_data(http_response_t *response, int *datalen)
158 | {
159 | assert(response);
160 | assert(datalen);
161 | assert(response->complete);
162 |
163 | *datalen = response->data_length;
164 | return response->data;
165 | }
166 |
--------------------------------------------------------------------------------
/airplay/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 |
22 | void http_response_add_header(http_response_t *response, const char *name, const char *value);
23 | void http_response_finish(http_response_t *response, const char *data, int datalen);
24 |
25 | void http_response_set_disconnect(http_response_t *response, int disconnect);
26 | int http_response_get_disconnect(http_response_t *response);
27 |
28 | const char *http_response_get_data(http_response_t *response, int *datalen);
29 |
30 | void http_response_destroy(http_response_t *response);
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/airplay/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 | typedef struct http_connection_s http_connection_t;
24 |
25 | struct httpd_callbacks_s {
26 | void* opaque;
27 | void* (*conn_init)(void *opaque, http_connection_t* http_conn, unsigned char *local, int locallen, unsigned char *remote, int remotelen);
28 | void (*conn_request)(void *ptr, http_request_t *request, http_response_t **response);
29 | void (*conn_destroy)(void *ptr);
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 | #endif
44 |
--------------------------------------------------------------------------------
/airplay/llhttp/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | This software is licensed under the MIT License.
2 |
3 | Copyright Fedor Indutny, 2018.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a
6 | copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to permit
10 | persons to whom the Software is furnished to do so, subject to the
11 | following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included
14 | in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
19 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 | USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/airplay/llhttp/http.c:
--------------------------------------------------------------------------------
1 | #include
2 | #ifndef LLHTTP__TEST
3 | # include "llhttp.h"
4 | #else
5 | # define llhttp_t llparse_t
6 | #endif /* */
7 |
8 | int llhttp_message_needs_eof(const llhttp_t* parser);
9 | int llhttp_should_keep_alive(const llhttp_t* parser);
10 |
11 | int llhttp__before_headers_complete(llhttp_t* parser, const char* p,
12 | const char* endp) {
13 | /* Set this here so that on_headers_complete() callbacks can see it */
14 | if ((parser->flags & F_UPGRADE) &&
15 | (parser->flags & F_CONNECTION_UPGRADE)) {
16 | /* For responses, "Upgrade: foo" and "Connection: upgrade" are
17 | * mandatory only when it is a 101 Switching Protocols response,
18 | * otherwise it is purely informational, to announce support.
19 | */
20 | parser->upgrade =
21 | (parser->type == HTTP_REQUEST || parser->status_code == 101);
22 | } else {
23 | parser->upgrade = (parser->method == HTTP_CONNECT);
24 | }
25 | return 0;
26 | }
27 |
28 |
29 | /* Return values:
30 | * 0 - No body, `restart`, message_complete
31 | * 1 - CONNECT request, `restart`, message_complete, and pause
32 | * 2 - chunk_size_start
33 | * 3 - body_identity
34 | * 4 - body_identity_eof
35 | * 5 - invalid transfer-encoding for request
36 | */
37 | int llhttp__after_headers_complete(llhttp_t* parser, const char* p,
38 | const char* endp) {
39 | int hasBody;
40 |
41 | hasBody = parser->flags & F_CHUNKED || parser->content_length > 0;
42 | if (parser->upgrade && (parser->method == HTTP_CONNECT ||
43 | (parser->flags & F_SKIPBODY) || !hasBody)) {
44 | /* Exit, the rest of the message is in a different protocol. */
45 | return 1;
46 | }
47 |
48 | if (parser->flags & F_SKIPBODY) {
49 | return 0;
50 | } else if (parser->flags & F_CHUNKED) {
51 | /* chunked encoding - ignore Content-Length header, prepare for a chunk */
52 | return 2;
53 | } else if (parser->flags & F_TRANSFER_ENCODING) {
54 | if (parser->type == HTTP_REQUEST &&
55 | (parser->lenient_flags & LENIENT_CHUNKED_LENGTH) == 0) {
56 | /* RFC 7230 3.3.3 */
57 |
58 | /* If a Transfer-Encoding header field
59 | * is present in a request and the chunked transfer coding is not
60 | * the final encoding, the message body length cannot be determined
61 | * reliably; the server MUST respond with the 400 (Bad Request)
62 | * status code and then close the connection.
63 | */
64 | return 5;
65 | } else {
66 | /* RFC 7230 3.3.3 */
67 |
68 | /* If a Transfer-Encoding header field is present in a response and
69 | * the chunked transfer coding is not the final encoding, the
70 | * message body length is determined by reading the connection until
71 | * it is closed by the server.
72 | */
73 | return 4;
74 | }
75 | } else {
76 | if (!(parser->flags & F_CONTENT_LENGTH)) {
77 | if (!llhttp_message_needs_eof(parser)) {
78 | /* Assume content-length 0 - read the next */
79 | return 0;
80 | } else {
81 | /* Read body until EOF */
82 | return 4;
83 | }
84 | } else if (parser->content_length == 0) {
85 | /* Content-Length header given but zero: Content-Length: 0\r\n */
86 | return 0;
87 | } else {
88 | /* Content-Length header given and non-zero */
89 | return 3;
90 | }
91 | }
92 | }
93 |
94 |
95 | int llhttp__after_message_complete(llhttp_t* parser, const char* p,
96 | const char* endp) {
97 | int should_keep_alive;
98 |
99 | should_keep_alive = llhttp_should_keep_alive(parser);
100 | parser->finish = HTTP_FINISH_SAFE;
101 | parser->flags = 0;
102 |
103 | /* NOTE: this is ignored in loose parsing mode */
104 | return should_keep_alive;
105 | }
106 |
107 |
108 | int llhttp_message_needs_eof(const llhttp_t* parser) {
109 | if (parser->type == HTTP_REQUEST) {
110 | return 0;
111 | }
112 |
113 | /* See RFC 2616 section 4.4 */
114 | if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */
115 | parser->status_code == 204 || /* No Content */
116 | parser->status_code == 304 || /* Not Modified */
117 | (parser->flags & F_SKIPBODY)) { /* response to a HEAD request */
118 | return 0;
119 | }
120 |
121 | /* RFC 7230 3.3.3, see `llhttp__after_headers_complete` */
122 | if ((parser->flags & F_TRANSFER_ENCODING) &&
123 | (parser->flags & F_CHUNKED) == 0) {
124 | return 1;
125 | }
126 |
127 | if (parser->flags & (F_CHUNKED | F_CONTENT_LENGTH)) {
128 | return 0;
129 | }
130 |
131 | return 1;
132 | }
133 |
134 |
135 | int llhttp_should_keep_alive(const llhttp_t* parser) {
136 | if (parser->http_major > 0 && parser->http_minor > 0) {
137 | /* HTTP/1.1 */
138 | if (parser->flags & F_CONNECTION_CLOSE) {
139 | return 0;
140 | }
141 | } else {
142 | /* HTTP/1.0 or earlier */
143 | if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {
144 | return 0;
145 | }
146 | }
147 |
148 | return !llhttp_message_needs_eof(parser);
149 | }
150 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/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 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | /* Define syslog style log levels */
23 | #define LOGGER_EMERG 0 /* system is unusable */
24 | #define LOGGER_ALERT 1 /* action must be taken immediately */
25 | #define LOGGER_CRIT 2 /* critical conditions */
26 | #define LOGGER_ERR 3 /* error conditions */
27 | #define LOGGER_WARNING 4 /* warning conditions */
28 | #define LOGGER_NOTICE 5 /* normal but significant condition */
29 | #define LOGGER_INFO 6 /* informational */
30 | #define LOGGER_DEBUG 7 /* debug-level messages */
31 |
32 | typedef void (*logger_callback_t)(void *cls, int level, const char *msg);
33 |
34 | typedef struct logger_s logger_t;
35 |
36 | logger_t *logger_init();
37 | void logger_destroy(logger_t *logger);
38 |
39 | void logger_set_level(logger_t *logger, int level);
40 | void logger_set_callback(logger_t *logger, logger_callback_t callback, void *cls);
41 |
42 | void logger_log(logger_t *logger, int level, const char *fmt, ...);
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 |
48 | #endif
49 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/mirror_buffer.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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 "mirror_buffer.h"
16 | #include "raop_rtp.h"
17 | #include "raop_rtp.h"
18 | #include
19 |
20 | #include "aes.h"
21 | #include "ed25519/sha512.h"
22 |
23 | #include "compat.h"
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 |
31 | //#define DUMP_KEI_IV
32 | struct mirror_buffer_s {
33 | logger_t *logger;
34 | struct AES_ctx aes_ctx;
35 | int nextDecryptCount;
36 | uint8_t og[16];
37 | /* audio aes key is used in a hash for the video aes key and iv */
38 | unsigned char aeskey_audio[RAOP_AESKEY_LEN];
39 | };
40 |
41 | void
42 | mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, const uint64_t *streamConnectionID)
43 | {
44 | unsigned char aeskey_video[64];
45 | unsigned char aesiv_video[64];
46 |
47 | assert(mirror_buffer);
48 | assert(streamConnectionID);
49 |
50 | /* AES key and IV */
51 | // Need secondary processing to use
52 |
53 | sprintf((char*) aeskey_video, "AirPlayStreamKey%" PRIu64, *streamConnectionID);
54 | sprintf((char*) aesiv_video, "AirPlayStreamIV%" PRIu64, *streamConnectionID);
55 |
56 | sha512_context ctx;
57 | sha512_init(&ctx);
58 | sha512_update(&ctx, aeskey_video, strlen((char*) aeskey_video));
59 | sha512_update(&ctx, mirror_buffer->aeskey_audio, RAOP_AESKEY_LEN);
60 | sha512_final(&ctx, aeskey_video);
61 |
62 | sha512_init(&ctx);
63 | sha512_update(&ctx, aesiv_video, strlen((char*) aesiv_video));
64 | sha512_update(&ctx, mirror_buffer->aeskey_audio, RAOP_AESKEY_LEN);
65 | sha512_final(&ctx, aesiv_video);
66 |
67 | // Need to be initialized externally
68 | AES_init_ctx_iv(&mirror_buffer->aes_ctx, aeskey_video, aesiv_video);
69 |
70 | #ifdef DUMP_KEI_IV
71 | FILE* keyfile = fopen("/sdcard/111.keyiv", "wb");
72 | fwrite(aeskey_video, 16, 1, keyfile);
73 | fwrite(aesiv_video, 16, 1, keyfile);
74 | fclose(keyfile);
75 | #endif
76 | }
77 |
78 | mirror_buffer_t *
79 | mirror_buffer_init(logger_t *logger, const unsigned char *aeskey)
80 | {
81 | mirror_buffer_t *mirror_buffer;
82 | assert(aeskey);
83 | mirror_buffer = calloc(1, sizeof(mirror_buffer_t));
84 | if (!mirror_buffer) {
85 | return NULL;
86 | }
87 | memcpy(mirror_buffer->aeskey_audio, aeskey, RAOP_AESKEY_LEN);
88 | mirror_buffer->logger = logger;
89 | mirror_buffer->nextDecryptCount = 0;
90 | return mirror_buffer;
91 | }
92 |
93 | void mirror_buffer_decrypt(mirror_buffer_t *mirror_buffer, unsigned char* input, unsigned char* output, int inputLen) {
94 | // Start decrypting
95 | if (mirror_buffer->nextDecryptCount > 0) {//mirror_buffer->nextDecryptCount = 10
96 | for (int i = 0; i < mirror_buffer->nextDecryptCount; i++) {
97 | output[i] = (input[i] ^ mirror_buffer->og[(16 - mirror_buffer->nextDecryptCount) + i]);
98 | }
99 | }
100 | // Handling encrypted bytes
101 | int encryptlen = ((inputLen - mirror_buffer->nextDecryptCount) / 16) * 16;
102 | // Aes decryption
103 | AES_CTR_xcrypt_buffer(&mirror_buffer->aes_ctx, input + mirror_buffer->nextDecryptCount, encryptlen);
104 |
105 | // Copy to output
106 | memcpy(output + mirror_buffer->nextDecryptCount, input + mirror_buffer->nextDecryptCount, encryptlen);
107 | int outputlength = mirror_buffer->nextDecryptCount + encryptlen;
108 | // Processing remaining length
109 | int restlen = (inputLen - mirror_buffer->nextDecryptCount) % 16;
110 | int reststart = inputLen - restlen;
111 | mirror_buffer->nextDecryptCount = 0;
112 | if (restlen > 0) {
113 | memset(mirror_buffer->og, 0, 16);
114 | memcpy(mirror_buffer->og, input + reststart, restlen);
115 | AES_CTR_xcrypt_buffer(&mirror_buffer->aes_ctx, mirror_buffer->og, 16);
116 | for (int j = 0; j < restlen; j++) {
117 | output[reststart + j] = mirror_buffer->og[j];
118 | }
119 | outputlength += restlen;
120 | mirror_buffer->nextDecryptCount = 16 - restlen;// Difference 16-6=10 bytes
121 | }
122 | }
123 |
124 | void
125 | mirror_buffer_destroy(mirror_buffer_t *mirror_buffer)
126 | {
127 | if (mirror_buffer) {
128 | free(mirror_buffer);
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/airplay/mirror_buffer.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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 MIRROR_BUFFER_H
16 | #define MIRROR_BUFFER_H
17 |
18 | #include
19 | #include "logger.h"
20 |
21 | typedef struct mirror_buffer_s mirror_buffer_t;
22 |
23 |
24 | mirror_buffer_t *mirror_buffer_init( logger_t *logger, const unsigned char *aeskey);
25 | void mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, const uint64_t *streamConnectionID);
26 | void mirror_buffer_decrypt(mirror_buffer_t *raop_mirror, unsigned char* input, unsigned char* output, int datalen);
27 | void mirror_buffer_destroy(mirror_buffer_t *mirror_buffer);
28 | #endif //MIRROR_BUFFER_H
29 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/pairing.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2018 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 PAIRING_H
16 | #define PAIRING_H
17 |
18 | #include "aes.h"
19 | #include "aes_ctr.h"
20 | #include "crypto/crypto.h"
21 | #include "ed25519/sha512.h"
22 | #include "ed25519/ed25519.h"
23 | #include "curve25519/curve25519.h"
24 |
25 | #define X25519_KEY_SIZE 32
26 | #define ED25519_KEY_SIZE 32
27 | #define AES_128_BLOCK_SIZE 16
28 | #define SHA512_DIGEST_LENGTH 64
29 | #define PAIRING_SIG_SIZE (2 * X25519_KEY_SIZE)
30 |
31 | typedef struct pairing_s pairing_t;
32 | typedef struct pairing_session_s pairing_session_t;
33 |
34 | pairing_t *pairing_init_generate();
35 | void pairing_get_public_key(pairing_t *pairing, unsigned char public_key[ED25519_KEY_SIZE]);
36 |
37 | pairing_session_t *pairing_session_init(pairing_t *pairing);
38 | void pairing_session_set_setup_status(pairing_session_t *session);
39 | int pairing_session_check_handshake_status(pairing_session_t *session);
40 | int pairing_session_handshake(pairing_session_t *session, const unsigned char ecdh_key[X25519_KEY_SIZE],
41 | const unsigned char ed_key[ED25519_KEY_SIZE]);
42 | int pairing_session_get_public_key(pairing_session_t *session, unsigned char ecdh_key[X25519_KEY_SIZE]);
43 | int pairing_session_get_signature(pairing_session_t *session, unsigned char signature[PAIRING_SIG_SIZE]);
44 | int pairing_session_finish(pairing_session_t *session, const unsigned char signature[PAIRING_SIG_SIZE]);
45 | void pairing_session_destroy(pairing_session_t *session);
46 |
47 | void pairing_destroy(pairing_t *pairing);
48 |
49 | void pairing_get_ecdh_secret_key(pairing_session_t *session, unsigned char ecdh_secret[X25519_KEY_SIZE]);
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/airplay/playfair/modified_md5.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #define printf(...) (void)0;
8 |
9 | int shift[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
10 | 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
11 | 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
12 | 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
13 |
14 | uint32_t F(uint32_t B, uint32_t C, uint32_t D)
15 | {
16 | return (B & C) | (~B & D);
17 | }
18 |
19 | uint32_t G(uint32_t B, uint32_t C, uint32_t D)
20 | {
21 | return (B & D) | (C & ~D);
22 | }
23 |
24 | uint32_t H(uint32_t B, uint32_t C, uint32_t D)
25 | {
26 | return B ^ C ^ D;
27 | }
28 |
29 | uint32_t I(uint32_t B, uint32_t C, uint32_t D)
30 | {
31 | return C ^ (B | ~D);
32 | }
33 |
34 |
35 | uint32_t rol(uint32_t input, int count)
36 | {
37 | return ((input << count) & 0xffffffff) | (input & 0xffffffff) >> (32-count);
38 | }
39 |
40 | void swap(uint32_t* a, uint32_t* b)
41 | {
42 | printf("%08x <-> %08x\n", *a, *b);
43 | uint32_t c = *a;
44 | *a = *b;
45 | *b = c;
46 | }
47 |
48 | void modified_md5(unsigned char* originalblockIn, unsigned char* keyIn, unsigned char* keyOut)
49 | {
50 | unsigned char blockIn[64];
51 | uint32_t* block_words = (uint32_t*)blockIn;
52 | uint32_t* key_words = (uint32_t*)keyIn;
53 | uint32_t* out_words = (uint32_t*)keyOut;
54 | uint32_t A, B, C, D, Z, tmp;
55 | int i;
56 |
57 | memcpy(blockIn, originalblockIn, 64);
58 |
59 | // Each cycle does something like this:
60 | A = key_words[0];
61 | B = key_words[1];
62 | C = key_words[2];
63 | D = key_words[3];
64 | for (i = 0; i < 64; i++)
65 | {
66 | uint32_t input;
67 | int j;
68 | if (i < 16)
69 | j = i;
70 | else if (i < 32)
71 | j = (5*i + 1) % 16;
72 | else if (i < 48)
73 | j = (3*i + 5) % 16;
74 | else if (i < 64)
75 | j = 7*i % 16;
76 |
77 | input = blockIn[4*j] << 24 | blockIn[4*j+1] << 16 | blockIn[4*j+2] << 8 | blockIn[4*j+3];
78 | printf("Key = %08x\n", A);
79 | Z = A + input + (int)(long long)((1LL << 32) * fabs(sin(i + 1)));
80 | if (i < 16)
81 | Z = rol(Z + F(B,C,D), shift[i]);
82 | else if (i < 32)
83 | Z = rol(Z + G(B,C,D), shift[i]);
84 | else if (i < 48)
85 | Z = rol(Z + H(B,C,D), shift[i]);
86 | else if (i < 64)
87 | Z = rol(Z + I(B,C,D), shift[i]);
88 | if (i == 63)
89 | printf("Ror is %08x\n", Z);
90 | printf("Output of round %d: %08X + %08X = %08X (shift %d, constant %08X)\n", i, Z, B, Z+B, shift[i], (int)(long long)((1LL << 32) * fabs(sin(i + 1))));
91 | Z = Z + B;
92 | tmp = D;
93 | D = C;
94 | C = B;
95 | B = Z;
96 | A = tmp;
97 | if (i == 31)
98 | {
99 | // swapsies
100 | swap(&block_words[A & 15], &block_words[B & 15]);
101 | swap(&block_words[C & 15], &block_words[D & 15]);
102 | swap(&block_words[(A & (15<<4))>>4], &block_words[(B & (15<<4))>>4]);
103 | swap(&block_words[(A & (15<<8))>>8], &block_words[(B & (15<<8))>>8]);
104 | swap(&block_words[(A & (15<<12))>>12], &block_words[(B & (15<<12))>>12]);
105 | }
106 | }
107 | printf("%08X %08X %08X %08X\n", A, B, C, D);
108 | // Now we can actually compute the output
109 | printf("Out:\n");
110 | printf("%08x + %08x = %08x\n", key_words[0], A, key_words[0] + A);
111 | printf("%08x + %08x = %08x\n", key_words[1], B, key_words[1] + B);
112 | printf("%08x + %08x = %08x\n", key_words[2], C, key_words[2] + C);
113 | printf("%08x + %08x = %08x\n", key_words[3], D, key_words[3] + D);
114 | out_words[0] = key_words[0] + A;
115 | out_words[1] = key_words[1] + B;
116 | out_words[2] = key_words[2] + C;
117 | out_words[3] = key_words[3] + D;
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/airplay/playfair/playfair.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "playfair.h"
4 |
5 | void generate_key_schedule(unsigned char* key_material, uint32_t key_schedule[11][4]);
6 | void generate_session_key(unsigned char* oldSap, unsigned char* messageIn, unsigned char* sessionKey);
7 | void cycle(unsigned char* block, uint32_t key_schedule[11][4]);
8 | void z_xor(unsigned char* in, unsigned char* out, int blocks);
9 | void x_xor(unsigned char* in, unsigned char* out, int blocks);
10 |
11 | extern unsigned char default_sap[];
12 |
13 | void playfair_decrypt(unsigned char* message3, unsigned char* cipherText, unsigned char* keyOut)
14 | {
15 | unsigned char* chunk1 = &cipherText[16];
16 | unsigned char* chunk2 = &cipherText[56];
17 | int i;
18 | unsigned char blockIn[16];
19 | unsigned char sapKey[16];
20 | uint32_t key_schedule[11][4];
21 | generate_session_key(default_sap, message3, sapKey);
22 | generate_key_schedule(sapKey, key_schedule);
23 | z_xor(chunk2, blockIn, 1);
24 | cycle(blockIn, key_schedule);
25 | for (i = 0; i < 16; i++) {
26 | keyOut[i] = blockIn[i] ^ chunk1[i];
27 | }
28 | x_xor(keyOut, keyOut, 1);
29 | z_xor(keyOut, keyOut, 1);
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/airplay/playfair/playfair.h:
--------------------------------------------------------------------------------
1 | #ifndef PLAYFAIR_H
2 | #define PLAYFAIR_H
3 |
4 | void playfair_decrypt(unsigned char* message3, unsigned char* cipherText, unsigned char* keyOut);
5 |
6 | #endif
7 |
--------------------------------------------------------------------------------
/airplay/playfair/sap_hash.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #define printf(...) (void)0;
6 |
7 | void garble(unsigned char*, unsigned char*, unsigned char*, unsigned char*, unsigned char*);
8 |
9 | unsigned char rol8(unsigned char input, int count)
10 | {
11 | return ((input << count) & 0xff) | (input & 0xff) >> (8-count);
12 | }
13 |
14 | uint32_t rol8x(unsigned char input, int count)
15 | {
16 | return ((input << count)) | (input) >> (8-count);
17 | }
18 |
19 |
20 | void sap_hash(unsigned char* blockIn, unsigned char* keyOut)
21 | {
22 | uint32_t* block_words = (uint32_t*)blockIn;
23 | uint32_t* out_words = (uint32_t*)keyOut;
24 | unsigned char buffer0[20] = {0x96, 0x5F, 0xC6, 0x53, 0xF8, 0x46, 0xCC, 0x18, 0xDF, 0xBE, 0xB2, 0xF8, 0x38, 0xD7, 0xEC, 0x22, 0x03, 0xD1, 0x20, 0x8F};
25 | unsigned char buffer1[210];
26 | unsigned char buffer2[35] = {0x43, 0x54, 0x62, 0x7A, 0x18, 0xC3, 0xD6, 0xB3, 0x9A, 0x56, 0xF6, 0x1C, 0x14, 0x3F, 0x0C, 0x1D, 0x3B, 0x36, 0x83, 0xB1, 0x39, 0x51, 0x4A, 0xAA, 0x09, 0x3E, 0xFE, 0x44, 0xAF, 0xDE, 0xC3, 0x20, 0x9D, 0x42, 0x3A};
27 | unsigned char buffer3[132];
28 | unsigned char buffer4[21] = {0xED, 0x25, 0xD1, 0xBB, 0xBC, 0x27, 0x9F, 0x02, 0xA2, 0xA9, 0x11, 0x00, 0x0C, 0xB3, 0x52, 0xC0, 0xBD, 0xE3, 0x1B, 0x49, 0xC7};
29 | int i0_index[11] = {18, 22, 23, 0, 5, 19, 32, 31, 10, 21, 30};
30 | uint8_t w,x,y,z;
31 | int i, j;
32 |
33 | // Load the input into the buffer
34 | for (i = 0; i < 210; i++)
35 | {
36 | // We need to swap the byte order around so it is the right endianness
37 | uint32_t in_word = block_words[((i % 64)>>2)];
38 | uint32_t in_byte = (in_word >> ((3-(i % 4)) << 3)) & 0xff;
39 | buffer1[i] = in_byte;
40 | }
41 | // Next a scrambling
42 | for (i = 0; i < 840; i++)
43 | {
44 | // We have to do unsigned, 32-bit modulo, or we get the wrong indices
45 | x = buffer1[((i-155) & 0xffffffff) % 210];
46 | y = buffer1[((i-57) & 0xffffffff) % 210];
47 | z = buffer1[((i-13) & 0xffffffff) % 210];
48 | w = buffer1[(i & 0xffffffff) % 210];
49 | buffer1[i % 210] = (rol8(y, 5) + (rol8(z, 3) ^ w) - rol8(x,7)) & 0xff;
50 | }
51 | printf("Garbling...\n");
52 | // I have no idea what this is doing (yet), but it gives the right output
53 | garble(buffer0, buffer1, buffer2, buffer3, buffer4);
54 |
55 | // Fill the output with 0xE1
56 | for (i = 0; i < 16; i++)
57 | keyOut[i] = 0xE1;
58 |
59 | // Now we use all the buffers we have calculated to grind out the output. First buffer3
60 | for (i = 0; i < 11; i++)
61 | {
62 | // Note that this is addition (mod 255) and not XOR
63 | // Also note that we only use certain indices
64 | // And that index 3 is hard-coded to be 0x3d (Maybe we can hack this up by changing buffer3[0] to be 0xdc?
65 | if (i == 3)
66 | keyOut[i] = 0x3d;
67 | else
68 | keyOut[i] = ((keyOut[i] + buffer3[i0_index[i] * 4]) & 0xff);
69 | }
70 |
71 | // Then buffer0
72 | for (i = 0; i < 20; i++)
73 | keyOut[i % 16] ^= buffer0[i];
74 |
75 | // Then buffer2
76 | for (i = 0; i < 35; i++)
77 | keyOut[i % 16] ^= buffer2[i];
78 |
79 | // Do buffer1
80 | for (i = 0; i < 210; i++)
81 | keyOut[(i % 16)] ^= buffer1[i];
82 |
83 |
84 | // Now we do a kind of reverse-scramble
85 | for (j = 0; j < 16; j++)
86 | {
87 | for (i = 0; i < 16; i++)
88 | {
89 | x = keyOut[((i-7) & 0xffffffff) % 16];
90 | y = keyOut[i % 16];
91 | z = keyOut[((i-37) & 0xffffffff) % 16];
92 | w = keyOut[((i-177) & 0xffffffff) % 16];
93 | keyOut[i] = rol8(x, 1) ^ y ^ rol8(z, 6) ^ rol8(w, 5);
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/airplay/plist/base64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * base64.c
3 | * base64 encode/decode implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #include
22 | #include "base64.h"
23 |
24 | static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
25 | static const char base64_pad = '=';
26 |
27 | static const signed char base64_table[256] = {
28 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
29 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
31 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -2, -1, -1,
32 | -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
33 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
34 | -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
35 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
36 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
39 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
44 | };
45 |
46 | size_t base64encode(char *outbuf, const unsigned char *buf, size_t size)
47 | {
48 | if (!outbuf || !buf || (size <= 0)) {
49 | return 0;
50 | }
51 |
52 | size_t n = 0;
53 | size_t m = 0;
54 | unsigned char input[3];
55 | unsigned int output[4];
56 | while (n < size) {
57 | input[0] = buf[n];
58 | input[1] = (n+1 < size) ? buf[n+1] : 0;
59 | input[2] = (n+2 < size) ? buf[n+2] : 0;
60 | output[0] = input[0] >> 2;
61 | output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
62 | output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
63 | output[3] = input[2] & 63;
64 | outbuf[m++] = base64_str[(int)output[0]];
65 | outbuf[m++] = base64_str[(int)output[1]];
66 | outbuf[m++] = (n+1 < size) ? base64_str[(int)output[2]] : base64_pad;
67 | outbuf[m++] = (n+2 < size) ? base64_str[(int)output[3]] : base64_pad;
68 | n+=3;
69 | }
70 | outbuf[m] = 0; // 0-termination!
71 | return m;
72 | }
73 |
74 | unsigned char *base64decode(const char *buf, size_t *size)
75 | {
76 | if (!buf || !size) return NULL;
77 | size_t len = (*size > 0) ? *size : strlen(buf);
78 | if (len <= 0) return NULL;
79 | unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3);
80 | const char *ptr = buf;
81 | int p = 0;
82 | int wv, w1, w2, w3, w4;
83 | int tmpval[4];
84 | int tmpcnt = 0;
85 |
86 | do {
87 | while (ptr < buf+len && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')) {
88 | ptr++;
89 | }
90 | if (*ptr == '\0' || ptr >= buf+len) {
91 | break;
92 | }
93 | if ((wv = base64_table[(int)(unsigned char)*ptr++]) == -1) {
94 | continue;
95 | }
96 | tmpval[tmpcnt++] = wv;
97 | if (tmpcnt == 4) {
98 | tmpcnt = 0;
99 | w1 = tmpval[0];
100 | w2 = tmpval[1];
101 | w3 = tmpval[2];
102 | w4 = tmpval[3];
103 |
104 | if (w1 >= 0 && w2 >= 0) {
105 | outbuf[p++] = (unsigned char)(((w1 << 2) + (w2 >> 4)) & 0xFF);
106 | }
107 | if (w2 >= 0 && w3 >= 0) {
108 | outbuf[p++] = (unsigned char)(((w2 << 4) + (w3 >> 2)) & 0xFF);
109 | }
110 | if (w3 >= 0 && w4 >= 0) {
111 | outbuf[p++] = (unsigned char)(((w3 << 6) + w4) & 0xFF);
112 | }
113 | }
114 | } while (1);
115 |
116 | outbuf[p] = 0;
117 | *size = p;
118 | return outbuf;
119 | }
120 |
--------------------------------------------------------------------------------
/airplay/plist/base64.h:
--------------------------------------------------------------------------------
1 | /*
2 | * base64.h
3 | * base64 encode/decode implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #ifndef BASE64_H
22 | #define BASE64_H
23 | #include
24 |
25 | size_t base64encode(char *outbuf, const unsigned char *buf, size_t size);
26 | unsigned char *base64decode(const char *buf, size_t *size);
27 |
28 | #endif
29 |
--------------------------------------------------------------------------------
/airplay/plist/bytearray.c:
--------------------------------------------------------------------------------
1 | /*
2 | * bytearray.c
3 | * simple byte array implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #include
22 | #include "bytearray.h"
23 |
24 | #define PAGE_SIZE 4096
25 |
26 | bytearray_t *byte_array_new(size_t initial)
27 | {
28 | bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t));
29 | a->capacity = (initial > PAGE_SIZE) ? (initial+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE;
30 | a->data = malloc(a->capacity);
31 | a->len = 0;
32 | return a;
33 | }
34 |
35 | void byte_array_free(bytearray_t *ba)
36 | {
37 | if (!ba) return;
38 | if (ba->data) {
39 | free(ba->data);
40 | }
41 | free(ba);
42 | }
43 |
44 | void byte_array_grow(bytearray_t *ba, size_t amount)
45 | {
46 | size_t increase = (amount > PAGE_SIZE) ? (amount+(PAGE_SIZE-1)) & (~(PAGE_SIZE-1)) : PAGE_SIZE;
47 | ba->data = realloc(ba->data, ba->capacity + increase);
48 | ba->capacity += increase;
49 | }
50 |
51 | void byte_array_append(bytearray_t *ba, void *buf, size_t len)
52 | {
53 | if (!ba || !ba->data || (len <= 0)) return;
54 | size_t remaining = ba->capacity-ba->len;
55 | if (len > remaining) {
56 | size_t needed = len - remaining;
57 | byte_array_grow(ba, needed);
58 | }
59 | memcpy(((char*)ba->data) + ba->len, buf, len);
60 | ba->len += len;
61 | }
62 |
--------------------------------------------------------------------------------
/airplay/plist/bytearray.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bytearray.h
3 | * header file for simple byte array implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #ifndef BYTEARRAY_H
22 | #define BYTEARRAY_H
23 | #include
24 |
25 | typedef struct bytearray_t {
26 | void *data;
27 | size_t len;
28 | size_t capacity;
29 | } bytearray_t;
30 |
31 | bytearray_t *byte_array_new(size_t initial);
32 | void byte_array_free(bytearray_t *ba);
33 | void byte_array_grow(bytearray_t *ba, size_t amount);
34 | void byte_array_append(bytearray_t *ba, void *buf, size_t len);
35 |
36 | #endif
37 |
--------------------------------------------------------------------------------
/airplay/plist/cnary.c:
--------------------------------------------------------------------------------
1 | /*
2 | * cnary.c
3 | *
4 | * Created on: Mar 9, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #include
25 |
26 | #include "node.h"
27 |
28 | int main(int argc, char* argv[]) {
29 | puts("Creating root node");
30 | node_t* root = node_create(NULL, NULL);
31 |
32 | puts("Creating child 1 node");
33 | node_t* one = node_create(root, NULL);
34 | puts("Creating child 2 node");
35 | node_t* two = node_create(root, NULL);
36 |
37 | puts("Creating child 3 node");
38 | node_t* three = node_create(one, NULL);
39 |
40 | puts("Debugging root node");
41 | node_debug(root);
42 |
43 | puts("Destroying root node");
44 | node_destroy(root);
45 | return 0;
46 | }
47 |
--------------------------------------------------------------------------------
/airplay/plist/hashtable.c:
--------------------------------------------------------------------------------
1 | /*
2 | * hashtable.c
3 | * really simple hash table implementation
4 | *
5 | * Copyright (c) 2011-2016 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #include "hashtable.h"
22 |
23 | hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func, free_func_t free_func)
24 | {
25 | hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t));
26 | int i;
27 | for (i = 0; i < 4096; i++) {
28 | ht->entries[i] = NULL;
29 | }
30 | ht->count = 0;
31 | ht->hash_func = hash_func;
32 | ht->compare_func = compare_func;
33 | ht->free_func = free_func;
34 | return ht;
35 | }
36 |
37 | void hash_table_destroy(hashtable_t *ht)
38 | {
39 | if (!ht) return;
40 |
41 | int i = 0;
42 | for (i = 0; i < 4096; i++) {
43 | if (ht->entries[i]) {
44 | hashentry_t* e = ht->entries[i];
45 | while (e) {
46 | if (ht->free_func) {
47 | ht->free_func(e->value);
48 | }
49 | hashentry_t* old = e;
50 | e = e->next;
51 | free(old);
52 | }
53 | }
54 | }
55 | free(ht);
56 | }
57 |
58 | void hash_table_insert(hashtable_t* ht, void *key, void *value)
59 | {
60 | if (!ht || !key) return;
61 |
62 | unsigned int hash = ht->hash_func(key);
63 |
64 | int idx0 = hash & 0xFFF;
65 |
66 | // get the idx0 list
67 | hashentry_t* e = ht->entries[idx0];
68 | while (e) {
69 | if (ht->compare_func(e->key, key)) {
70 | // element already present. replace value.
71 | e->value = value;
72 | return;
73 | }
74 | e = e->next;
75 | }
76 |
77 | // if we get here, the element is not yet in the list.
78 |
79 | // make a new entry.
80 | hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t));
81 | entry->key = key;
82 | entry->value = value;
83 | if (!ht->entries[idx0]) {
84 | // first entry
85 | entry->next = NULL;
86 | } else {
87 | // add to list
88 | entry->next = ht->entries[idx0];
89 | }
90 | ht->entries[idx0] = entry;
91 | ht->count++;
92 | }
93 |
94 | void* hash_table_lookup(hashtable_t* ht, void *key)
95 | {
96 | if (!ht || !key) return NULL;
97 | unsigned int hash = ht->hash_func(key);
98 |
99 | int idx0 = hash & 0xFFF;
100 |
101 | hashentry_t* e = ht->entries[idx0];
102 | while (e) {
103 | if (ht->compare_func(e->key, key)) {
104 | return e->value;
105 | }
106 | e = e->next;
107 | }
108 | return NULL;
109 | }
110 |
111 | void hash_table_remove(hashtable_t* ht, void *key)
112 | {
113 | if (!ht || !key) return;
114 |
115 | unsigned int hash = ht->hash_func(key);
116 |
117 | int idx0 = hash & 0xFFF;
118 |
119 | // get the idx0 list
120 | hashentry_t* e = ht->entries[idx0];
121 | hashentry_t* last = e;
122 | while (e) {
123 | if (ht->compare_func(e->key, key)) {
124 | // found element, remove it from the list
125 | hashentry_t* old = e;
126 | if (e == ht->entries[idx0]) {
127 | ht->entries[idx0] = e->next;
128 | } else {
129 | last->next = e->next;
130 | }
131 | if (ht->free_func) {
132 | ht->free_func(old->value);
133 | }
134 | free(old);
135 | return;
136 | }
137 | last = e;
138 | e = e->next;
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/airplay/plist/hashtable.h:
--------------------------------------------------------------------------------
1 | /*
2 | * hashtable.h
3 | * header file for really simple hash table implementation
4 | *
5 | * Copyright (c) 2011-2016 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #ifndef HASHTABLE_H
22 | #define HASHTABLE_H
23 | #include
24 |
25 | typedef struct hashentry_t {
26 | void *key;
27 | void *value;
28 | void *next;
29 | } hashentry_t;
30 |
31 | typedef unsigned int(*hash_func_t)(const void* key);
32 | typedef int (*compare_func_t)(const void *a, const void *b);
33 | typedef void (*free_func_t)(void *ptr);
34 |
35 | typedef struct hashtable_t {
36 | hashentry_t *entries[4096];
37 | size_t count;
38 | hash_func_t hash_func;
39 | compare_func_t compare_func;
40 | free_func_t free_func;
41 | } hashtable_t;
42 |
43 | hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func, free_func_t free_func);
44 | void hash_table_destroy(hashtable_t *ht);
45 |
46 | void hash_table_insert(hashtable_t* ht, void *key, void *value);
47 | void* hash_table_lookup(hashtable_t* ht, void *key);
48 | void hash_table_remove(hashtable_t* ht, void *key);
49 |
50 | #endif
51 |
--------------------------------------------------------------------------------
/airplay/plist/list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * list.c
3 | *
4 | * Created on: Mar 8, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #include
25 | #include
26 |
27 | #include "list.h"
28 |
29 | void list_init(list_t* list) {
30 | list->next = NULL;
31 | list->prev = list;
32 | }
33 |
34 |
35 | void list_destroy(list_t* list) {
36 | if(list) {
37 | free(list);
38 | }
39 | }
40 |
41 | int list_add(list_t* list, object_t* object) {
42 | return -1;
43 | }
44 |
45 | int list_remove(list_t* list, object_t* object) {
46 | return -1;
47 | }
48 |
--------------------------------------------------------------------------------
/airplay/plist/list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * list.h
3 | *
4 | * Created on: Mar 8, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #ifndef LIST_H_
25 | #define LIST_H_
26 |
27 | #include "object.h"
28 |
29 | typedef struct list_t {
30 | void* next;
31 | void* prev;
32 | } list_t;
33 |
34 | void list_init(struct list_t* list);
35 | void list_destroy(struct list_t* list);
36 |
37 | int list_add(struct list_t* list, struct object_t* object);
38 | int list_remove(struct list_t* list, struct object_t* object);
39 |
40 | #endif /* LIST_H_ */
41 |
--------------------------------------------------------------------------------
/airplay/plist/node.c:
--------------------------------------------------------------------------------
1 | /*
2 | * node.c
3 | *
4 | * Created on: Mar 7, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 | #include
24 | #include
25 | #include
26 |
27 | #include "node.h"
28 | #include "node_list.h"
29 |
30 | void node_destroy(node_t* node) {
31 | if(!node) return;
32 |
33 | if (node->children && node->children->count > 0) {
34 | node_t* ch;
35 | while ((ch = node->children->begin)) {
36 | node_list_remove(node->children, ch);
37 | node_destroy(ch);
38 | }
39 | }
40 | node_list_destroy(node->children);
41 | node->children = NULL;
42 |
43 | free(node);
44 | }
45 |
46 | node_t* node_create(node_t* parent, void* data) {
47 | int error = 0;
48 |
49 | node_t* node = (node_t*) malloc(sizeof(node_t));
50 | if(node == NULL) {
51 | return NULL;
52 | }
53 | memset(node, '\0', sizeof(node_t));
54 |
55 | node->data = data;
56 | node->next = NULL;
57 | node->prev = NULL;
58 | node->count = 0;
59 | node->parent = NULL;
60 | node->children = NULL;
61 |
62 | // Pass NULL to create a root node
63 | if(parent != NULL) {
64 | // This is a child node so attach it to it's parent
65 | error = node_attach(parent, node);
66 | if(error < 0) {
67 | // Unable to attach nodes
68 | printf("ERROR: %d \"Unable to attach nodes\"\n", error);
69 | node_destroy(node);
70 | return NULL;
71 | }
72 | }
73 |
74 | return node;
75 | }
76 |
77 | int node_attach(node_t* parent, node_t* child) {
78 | if (!parent || !child) return -1;
79 | child->parent = parent;
80 | if(!parent->children) {
81 | parent->children = node_list_create();
82 | }
83 | int res = node_list_add(parent->children, child);
84 | if (res == 0) {
85 | parent->count++;
86 | }
87 | return res;
88 | }
89 |
90 | int node_detach(node_t* parent, node_t* child) {
91 | if (!parent || !child) return -1;
92 | int node_index = node_list_remove(parent->children, child);
93 | if (node_index >= 0) {
94 | parent->count--;
95 | }
96 | return node_index;
97 | }
98 |
99 | int node_insert(node_t* parent, unsigned int node_index, node_t* child)
100 | {
101 | if (!parent || !child) return -1;
102 | child->parent = parent;
103 | if(!parent->children) {
104 | parent->children = node_list_create();
105 | }
106 | int res = node_list_insert(parent->children, node_index, child);
107 | if (res == 0) {
108 | parent->count++;
109 | }
110 | return res;
111 | }
112 |
113 | static void _node_debug(node_t* node, unsigned int depth) {
114 | unsigned int i = 0;
115 | node_t* current = NULL;
116 | for(i = 0; i < depth; i++) {
117 | printf("\t");
118 | }
119 | if(!node->parent) {
120 | printf("ROOT\n");
121 | }
122 |
123 | if(!node->children && node->parent) {
124 | printf("LEAF\n");
125 | } else {
126 | if(node->parent) {
127 | printf("NODE\n");
128 | }
129 | for (current = node_first_child(node); current; current = node_next_sibling(current)) {
130 | _node_debug(current, depth+1);
131 | }
132 | }
133 |
134 | }
135 |
136 | void node_debug(node_t* node)
137 | {
138 | _node_debug(node, 0);
139 | }
140 |
141 | unsigned int node_n_children(struct node_t* node)
142 | {
143 | if (!node) return 0;
144 | return node->count;
145 | }
146 |
147 | node_t* node_nth_child(struct node_t* node, unsigned int n)
148 | {
149 | if (!node || !node->children || !node->children->begin) return NULL;
150 | unsigned int node_index = 0;
151 | int found = 0;
152 | node_t *ch;
153 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
154 | if (node_index++ == n) {
155 | found = 1;
156 | break;
157 | }
158 | }
159 | if (!found) {
160 | return NULL;
161 | }
162 | return ch;
163 | }
164 |
165 | node_t* node_first_child(struct node_t* node)
166 | {
167 | if (!node || !node->children) return NULL;
168 | return node->children->begin;
169 | }
170 |
171 | node_t* node_prev_sibling(struct node_t* node)
172 | {
173 | if (!node) return NULL;
174 | return node->prev;
175 | }
176 |
177 | node_t* node_next_sibling(struct node_t* node)
178 | {
179 | if (!node) return NULL;
180 | return node->next;
181 | }
182 |
183 | int node_child_position(struct node_t* parent, node_t* child)
184 | {
185 | if (!parent || !parent->children || !parent->children->begin || !child) return -1;
186 | int node_index = 0;
187 | int found = 0;
188 | node_t *ch;
189 | for (ch = node_first_child(parent); ch; ch = node_next_sibling(ch)) {
190 | if (ch == child) {
191 | found = 1;
192 | break;
193 | }
194 | node_index++;
195 | }
196 | if (!found) {
197 | return -1;
198 | }
199 | return node_index;
200 | }
201 |
202 | node_t* node_copy_deep(node_t* node, copy_func_t copy_func)
203 | {
204 | if (!node) return NULL;
205 | void *data = NULL;
206 | if (copy_func) {
207 | data = copy_func(node->data);
208 | }
209 | node_t* copy = node_create(NULL, data);
210 | node_t* ch;
211 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
212 | node_t* cc = node_copy_deep(ch, copy_func);
213 | node_attach(copy, cc);
214 | }
215 | return copy;
216 | }
217 |
--------------------------------------------------------------------------------
/airplay/plist/node.h:
--------------------------------------------------------------------------------
1 | /*
2 | * node.h
3 | *
4 | * Created on: Mar 7, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #ifndef NODE_H_
25 | #define NODE_H_
26 |
27 | #include "object.h"
28 |
29 | #define NODE_TYPE 1;
30 |
31 | struct node_list_t;
32 |
33 | // This class implements the abstract iterator class
34 | typedef struct node_t {
35 | // Super class
36 | struct node_t* next;
37 | struct node_t* prev;
38 | unsigned int count;
39 |
40 | // Local Members
41 | void *data;
42 | struct node_t* parent;
43 | struct node_list_t* children;
44 | } node_t;
45 |
46 | void node_destroy(struct node_t* node);
47 | struct node_t* node_create(struct node_t* parent, void* data);
48 |
49 | int node_attach(struct node_t* parent, struct node_t* child);
50 | int node_detach(struct node_t* parent, struct node_t* child);
51 | int node_insert(struct node_t* parent, unsigned int index, struct node_t* child);
52 |
53 | unsigned int node_n_children(struct node_t* node);
54 | node_t* node_nth_child(struct node_t* node, unsigned int n);
55 | node_t* node_first_child(struct node_t* node);
56 | node_t* node_prev_sibling(struct node_t* node);
57 | node_t* node_next_sibling(struct node_t* node);
58 | int node_child_position(struct node_t* parent, node_t* child);
59 |
60 | typedef void* (*copy_func_t)(const void *src);
61 | node_t* node_copy_deep(node_t* node, copy_func_t copy_func);
62 |
63 | void node_debug(struct node_t* node);
64 |
65 | #endif /* NODE_H_ */
66 |
--------------------------------------------------------------------------------
/airplay/plist/node_list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * node_list.c
3 | *
4 | * Created on: Mar 8, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #include
25 | #include
26 | #include
27 |
28 | #include "list.h"
29 | #include "node.h"
30 | #include "node_list.h"
31 |
32 | void node_list_destroy(node_list_t* list) {
33 | if(list != NULL) {
34 | list_destroy((list_t*) list);
35 | }
36 | }
37 |
38 | node_list_t* node_list_create() {
39 | node_list_t* list = (node_list_t*) malloc(sizeof(node_list_t));
40 | if(list == NULL) {
41 | return NULL;
42 | }
43 | memset(list, '\0', sizeof(node_list_t));
44 |
45 | // Initialize structure
46 | list_init((list_t*) list);
47 | list->count = 0;
48 | return list;
49 | }
50 |
51 | int node_list_add(node_list_t* list, node_t* node) {
52 | if (!list || !node) return -1;
53 |
54 | // Find the last element in the list
55 | node_t* last = list->end;
56 |
57 | // Setup our new node as the new last element
58 | node->next = NULL;
59 | node->prev = last;
60 |
61 | // Set the next element of our old "last" element
62 | if (last) {
63 | // but only if the node list is not empty
64 | last->next = node;
65 | }
66 |
67 | // Set the lists prev to the new last element
68 | list->end = node;
69 |
70 | // Increment our node count for this list
71 | list->count++;
72 | return 0;
73 | }
74 |
75 | int node_list_insert(node_list_t* list, unsigned int node_index, node_t* node) {
76 | if (!list || !node) return -1;
77 | if (node_index >= list->count) {
78 | return node_list_add(list, node);
79 | }
80 |
81 | // Get the first element in the list
82 | node_t* cur = list->begin;
83 |
84 | unsigned int pos = 0;
85 | node_t* prev = NULL;
86 |
87 | if (node_index > 0) {
88 | while (pos < node_index) {
89 | prev = cur;
90 | cur = cur->next;
91 | pos++;
92 | }
93 | }
94 |
95 | if (prev) {
96 | // Set previous node
97 | node->prev = prev;
98 | // Set next node of our new node to next node of the previous node
99 | node->next = prev->next;
100 | // Set next node of previous node to our new node
101 | prev->next = node;
102 | } else {
103 | node->prev = NULL;
104 | // get old first element in list
105 | node->next = list->begin;
106 | // set new node as first element in list
107 | list->begin = node;
108 | }
109 |
110 | if (node->next == NULL) {
111 | // Set the lists prev to the new last element
112 | list->end = node;
113 | } else {
114 | // set prev of the new next element to our node
115 | node->next->prev = node;
116 | }
117 |
118 | // Increment our node count for this list
119 | list->count++;
120 | return 0;
121 | }
122 |
123 | int node_list_remove(node_list_t* list, node_t* node) {
124 | if (!list || !node) return -1;
125 | if (list->count == 0) return -1;
126 |
127 | int node_index = 0;
128 | node_t* n;
129 | for (n = list->begin; n; n = n->next) {
130 | if (node == n) {
131 | node_t* newnode = node->next;
132 | if (node->prev) {
133 | node->prev->next = newnode;
134 | if (newnode) {
135 | newnode->prev = node->prev;
136 | } else {
137 | // last element in the list
138 | list->end = node->prev;
139 | }
140 | } else {
141 | // we just removed the first element
142 | if (newnode) {
143 | newnode->prev = NULL;
144 | }
145 | list->begin = newnode;
146 | }
147 | list->count--;
148 | return node_index;
149 | }
150 | node_index++;
151 | }
152 | return -1;
153 | }
154 |
155 |
--------------------------------------------------------------------------------
/airplay/plist/node_list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * node_list.h
3 | *
4 | * Created on: Mar 8, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #ifndef NODE_LIST_H_
25 | #define NODE_LIST_H_
26 |
27 | struct node_t;
28 |
29 | // This class implements the list_t abstract class
30 | typedef struct node_list_t {
31 | // list_t members
32 | struct node_t* begin;
33 | struct node_t* end;
34 |
35 | // node_list_t members
36 | unsigned int count;
37 |
38 | } node_list_t;
39 |
40 | void node_list_destroy(struct node_list_t* list);
41 | struct node_list_t* node_list_create();
42 |
43 | int node_list_add(node_list_t* list, node_t* node);
44 | int node_list_insert(node_list_t* list, unsigned int index, node_t* node);
45 | int node_list_remove(node_list_t* list, node_t* node);
46 |
47 | #endif /* NODE_LIST_H_ */
48 |
--------------------------------------------------------------------------------
/airplay/plist/object.h:
--------------------------------------------------------------------------------
1 | /*
2 | * object.h
3 | *
4 | * Created on: Mar 8, 2011
5 | * Author: posixninja
6 | *
7 | * Copyright (c) 2011 Joshua Hill. All Rights Reserved.
8 | *
9 | * This library is free software; you can redistribute it and/or
10 | * modify it under the terms of the GNU Lesser General Public
11 | * License as published by the Free Software Foundation; either
12 | * version 2.1 of the License, or (at your option) any later version.
13 | *
14 | * This library is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 | * Lesser General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU Lesser General Public
20 | * License along with this library; if not, write to the Free Software
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 | */
23 |
24 | #ifndef OBJECT_H_
25 | #define OBJECT_H_
26 |
27 | #ifndef TRUE
28 | #define TRUE 1
29 | #endif
30 |
31 | #ifndef FALSE
32 | #define FALSE 0
33 | #endif
34 |
35 | typedef struct object_t {
36 | void* value;
37 | unsigned int type;
38 | unsigned int size;
39 | } object_t;
40 |
41 | #endif /* OBJECT_H_ */
42 |
--------------------------------------------------------------------------------
/airplay/plist/plist.h:
--------------------------------------------------------------------------------
1 | /*
2 | * plist.h
3 | * contains structures and the like for plists
4 | *
5 | * Copyright (c) 2008 Zach C. All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 |
22 | #ifndef PLIST_H
23 | #define PLIST_H
24 |
25 | #ifdef HAVE_CONFIG_H
26 | #include
27 | #endif
28 |
29 | #include "plist/plist.h"
30 |
31 | #include
32 | #include
33 | #include
34 |
35 | #ifdef _MSC_VER
36 | #pragma warning(disable:4996)
37 | #pragma warning(disable:4244)
38 | #endif
39 |
40 | #ifdef WIN32
41 | #define PLIST_API __declspec( dllexport )
42 | #else
43 | #ifdef HAVE_FVISIBILITY
44 | #define PLIST_API __attribute__((visibility("default")))
45 | #else
46 | #define PLIST_API
47 | #endif
48 | #endif
49 |
50 | struct plist_data_s
51 | {
52 | union
53 | {
54 | char boolval;
55 | uint64_t intval;
56 | double realval;
57 | char *strval;
58 | uint8_t *buff;
59 | void *hashtable;
60 | };
61 | uint64_t length;
62 | plist_type type;
63 | };
64 |
65 | typedef struct plist_data_s *plist_data_t;
66 |
67 | plist_t plist_new_node(plist_data_t data);
68 | plist_data_t plist_get_data(const plist_t node);
69 | plist_data_t plist_new_plist_data(void);
70 | void plist_free_data(plist_data_t data);
71 | int plist_data_compare(const void *a, const void *b);
72 |
73 |
74 | #endif
75 |
--------------------------------------------------------------------------------
/airplay/plist/ptrarray.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ptrarray.c
3 | * simple pointer array implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #include "ptrarray.h"
22 |
23 | ptrarray_t *ptr_array_new(int capacity)
24 | {
25 | ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t));
26 | pa->pdata = (void**)malloc(sizeof(void*) * capacity);
27 | pa->capacity = capacity;
28 | pa->capacity_step = (capacity > 4096) ? 4096 : capacity;
29 | pa->len = 0;
30 | return pa;
31 | }
32 |
33 | void ptr_array_free(ptrarray_t *pa)
34 | {
35 | if (!pa) return;
36 | if (pa->pdata) {
37 | free(pa->pdata);
38 | }
39 | free(pa);
40 | }
41 |
42 | void ptr_array_add(ptrarray_t *pa, void *data)
43 | {
44 | if (!pa || !pa->pdata || !data) return;
45 | size_t remaining = pa->capacity-pa->len;
46 | if (remaining == 0) {
47 | pa->pdata = realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
48 | pa->capacity += pa->capacity_step;
49 | }
50 | pa->pdata[pa->len] = data;
51 | pa->len++;
52 | }
53 |
54 | void* ptr_array_index(ptrarray_t *pa, size_t array_index)
55 | {
56 | if (!pa) return NULL;
57 | if (array_index >= pa->len) {
58 | return NULL;
59 | }
60 | return pa->pdata[array_index];
61 | }
62 |
--------------------------------------------------------------------------------
/airplay/plist/ptrarray.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ptrarray.h
3 | * header file for simple pointer array implementation
4 | *
5 | * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 | *
7 | * This library is free software; you can redistribute it and/or
8 | * modify it under the terms of the GNU Lesser General Public
9 | * License as published by the Free Software Foundation; either
10 | * version 2.1 of the License, or (at your option) any later version.
11 | *
12 | * This library is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | * Lesser General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Lesser General Public
18 | * License along with this library; if not, write to the Free Software
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 | */
21 | #ifndef PTRARRAY_H
22 | #define PTRARRAY_H
23 | #include
24 |
25 | typedef struct ptrarray_t {
26 | void **pdata;
27 | size_t len;
28 | size_t capacity;
29 | size_t capacity_step;
30 | } ptrarray_t;
31 |
32 | ptrarray_t *ptr_array_new(int capacity);
33 | void ptr_array_free(ptrarray_t *pa);
34 | void ptr_array_add(ptrarray_t *pa, void *data);
35 | void* ptr_array_index(ptrarray_t *pa, size_t index);
36 | #endif
37 |
--------------------------------------------------------------------------------
/airplay/plist/strbuf.h:
--------------------------------------------------------------------------------
1 | /*
2 | * strbuf.h
3 | * header file for simple string buffer, using the bytearray as underlying
4 | * structure.
5 | *
6 | * Copyright (c) 2016 Nikias Bassen, All Rights Reserved.
7 | *
8 | * This library is free software; you can redistribute it and/or
9 | * modify it under the terms of the GNU Lesser General Public
10 | * License as published by the Free Software Foundation; either
11 | * version 2.1 of the License, or (at your option) any later version.
12 | *
13 | * This library is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 | * Lesser General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU Lesser General Public
19 | * License along with this library; if not, write to the Free Software
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 | */
22 | #ifndef STRBUF_H
23 | #define STRBUF_H
24 | #include
25 | #include "bytearray.h"
26 |
27 | typedef struct bytearray_t strbuf_t;
28 |
29 | #define str_buf_new(__sz) byte_array_new(__sz)
30 | #define str_buf_free(__ba) byte_array_free(__ba)
31 | #define str_buf_grow(__ba, __am) byte_array_grow(__ba, __am)
32 | #define str_buf_append(__ba, __str, __len) byte_array_append(__ba, (void*)(__str), __len)
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/airplay/plist/time64.h:
--------------------------------------------------------------------------------
1 | #ifndef TIME64_H
2 | # define TIME64_H
3 |
4 | #include
5 | #ifdef HAVE_CONFIG_H
6 | #include "config.h"
7 | #endif
8 |
9 | /* Set our custom types */
10 | typedef long long Int64;
11 | typedef Int64 Time64_T;
12 | typedef Int64 Year;
13 |
14 |
15 | /* A copy of the tm struct but with a 64 bit year */
16 | struct TM64 {
17 | int tm_sec;
18 | int tm_min;
19 | int tm_hour;
20 | int tm_mday;
21 | int tm_mon;
22 | Year tm_year;
23 | int tm_wday;
24 | int tm_yday;
25 | int tm_isdst;
26 |
27 | #ifdef HAVE_TM_TM_GMTOFF
28 | long tm_gmtoff;
29 | #endif
30 |
31 | #ifdef HAVE_TM_TM_ZONE
32 | char *tm_zone;
33 | #endif
34 | };
35 |
36 |
37 | /* Decide which tm struct to use */
38 | #ifdef USE_TM64
39 | #define TM TM64
40 | #else
41 | #define TM tm
42 | #endif
43 |
44 |
45 | /* Declare public functions */
46 | struct TM *gmtime64_r (const Time64_T *, struct TM *);
47 | struct TM *localtime64_r (const Time64_T *, struct TM *);
48 |
49 | char *asctime64_r (const struct TM *, char *);
50 |
51 | char *ctime64_r (const Time64_T*, char*);
52 |
53 | Time64_T timegm64 (const struct TM *);
54 | Time64_T mktime64 (struct TM *);
55 | Time64_T timelocal64 (struct TM *);
56 |
57 |
58 | /* Not everyone has gm/localtime_r(), provide a replacement */
59 | #ifdef HAVE_LOCALTIME_R
60 | # define LOCALTIME_R(clock, result) localtime_r(clock, result)
61 | #else
62 | # define LOCALTIME_R(clock, result) fake_localtime_r(clock, result)
63 | #endif
64 | #ifdef HAVE_GMTIME_R
65 | # define GMTIME_R(clock, result) gmtime_r(clock, result)
66 | #else
67 | # define GMTIME_R(clock, result) fake_gmtime_r(clock, result)
68 | #endif
69 |
70 |
71 | /* Use a different asctime format depending on how big the year is */
72 | #ifdef USE_TM64
73 | #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %lld\n"
74 | #else
75 | #define TM64_ASCTIME_FORMAT "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n"
76 | #endif
77 |
78 | void copy_tm_to_TM64(const struct tm *src, struct TM *dest);
79 | void copy_TM64_to_tm(const struct TM *src, struct tm *dest);
80 |
81 | #endif
82 |
--------------------------------------------------------------------------------
/airplay/plist/time64_limits.h:
--------------------------------------------------------------------------------
1 | /*
2 | Maximum and minimum inputs your system's respective time functions
3 | can correctly handle. time64.h will use your system functions if
4 | the input falls inside these ranges and corresponding USE_SYSTEM_*
5 | constant is defined.
6 | */
7 |
8 | #ifndef TIME64_LIMITS_H
9 | #define TIME64_LIMITS_H
10 |
11 | #include
12 |
13 | /* Max/min for localtime() */
14 | #define SYSTEM_LOCALTIME_MAX 2147483647
15 | #define SYSTEM_LOCALTIME_MIN -2147483647-1
16 |
17 | /* Max/min for gmtime() */
18 | #define SYSTEM_GMTIME_MAX 2147483647
19 | #define SYSTEM_GMTIME_MIN -2147483647-1
20 |
21 | /* Max/min for mktime() */
22 | static const struct tm SYSTEM_MKTIME_MAX = {
23 | 7,
24 | 14,
25 | 19,
26 | 18,
27 | 0,
28 | 138,
29 | 1,
30 | 17,
31 | 0
32 | #ifdef HAVE_TM_TM_GMTOFF
33 | ,-28800
34 | #endif
35 | #ifdef HAVE_TM_TM_ZONE
36 | ,(char*)"PST"
37 | #endif
38 | };
39 |
40 | static const struct tm SYSTEM_MKTIME_MIN = {
41 | 52,
42 | 45,
43 | 12,
44 | 13,
45 | 11,
46 | 1,
47 | 5,
48 | 346,
49 | 0
50 | #ifdef HAVE_TM_TM_GMTOFF
51 | ,-28800
52 | #endif
53 | #ifdef HAVE_TM_TM_ZONE
54 | ,(char*)"PST"
55 | #endif
56 | };
57 |
58 | /* Max/min for timegm() */
59 | #ifdef HAVE_TIMEGM
60 | static const struct tm SYSTEM_TIMEGM_MAX = {
61 | 7,
62 | 14,
63 | 3,
64 | 19,
65 | 0,
66 | 138,
67 | 2,
68 | 18,
69 | 0
70 | #ifdef HAVE_TM_TM_GMTOFF
71 | ,0
72 | #endif
73 | #ifdef HAVE_TM_TM_ZONE
74 | ,(char*)"UTC"
75 | #endif
76 | };
77 |
78 | static const struct tm SYSTEM_TIMEGM_MIN = {
79 | 52,
80 | 45,
81 | 20,
82 | 13,
83 | 11,
84 | 1,
85 | 5,
86 | 346,
87 | 0
88 | #ifdef HAVE_TM_TM_GMTOFF
89 | ,0
90 | #endif
91 | #ifdef HAVE_TM_TM_ZONE
92 | ,(char*)"UTC"
93 | #endif
94 | };
95 | #endif /* HAVE_TIMEGM */
96 |
97 | #endif /* TIME64_LIMITS_H */
98 |
--------------------------------------------------------------------------------
/airplay/raop.h:
--------------------------------------------------------------------------------
1 | #ifndef RAOP_H
2 | #define RAOP_H
3 |
4 | #include "dnssd.h"
5 | #include "stream.h"
6 | #include "raop_ntp.h"
7 |
8 | #if defined (WIN32) && defined(DLL_EXPORT)
9 | # define RAOP_API __declspec(dllexport)
10 | #else
11 | # define RAOP_API
12 | #endif
13 |
14 | #ifdef __cplusplus
15 | extern "C" {
16 | #endif
17 |
18 |
19 | /* Define syslog style log levels */
20 | #define RAOP_LOG_EMERG 0 /* system is unusable */
21 | #define RAOP_LOG_ALERT 1 /* action must be taken immediately */
22 | #define RAOP_LOG_CRIT 2 /* critical conditions */
23 | #define RAOP_LOG_ERR 3 /* error conditions */
24 | #define RAOP_LOG_WARNING 4 /* warning conditions */
25 | #define RAOP_LOG_NOTICE 5 /* normal but significant condition */
26 | #define RAOP_LOG_INFO 6 /* informational */
27 | #define RAOP_LOG_DEBUG 7 /* debug-level messages */
28 |
29 |
30 | typedef struct raop_s raop_t;
31 |
32 | typedef void (*raop_log_callback_t)(void *cls, int level, const char *msg);
33 |
34 | typedef struct{
35 | char* osName;
36 | char* osVersion;
37 | char* model;
38 | char* name;
39 | } raop_device_info;
40 |
41 | typedef struct raop_connection_s{
42 | void* priv;
43 | void* usr_data;
44 | raop_device_info devInfo;
45 | } raop_connection_t;
46 |
47 | struct raop_callbacks_s {
48 | void* cls;
49 |
50 | void (*audio_process)(void *cls, raop_ntp_t *ntp, aac_decode_struct *data, raop_connection_t* conn);
51 | void (*video_process)(void *cls, raop_ntp_t *ntp, h264_decode_struct *data, raop_connection_t* conn);
52 |
53 | /* Optional but recommended callback functions */
54 | void (*conn_init)(void *cls, raop_connection_t* conn);
55 | void (*conn_destroy)(void *cls, raop_connection_t* conn);
56 | void (*conn_reset) (void *cls, int timeouts, bool reset_video, raop_connection_t* conn);
57 | void (*conn_teardown)(void *cls, bool *teardown_96, bool *teardown_110, raop_connection_t* conn);
58 | void (*audio_flush)(void *cls, raop_connection_t* conn);
59 | void (*video_flush)(void *cls, raop_connection_t* conn);
60 | void (*audio_set_volume)(void *cls, float volume, raop_connection_t* conn);
61 | void (*audio_set_metadata)(void *cls, const void *buffer, int buflen, raop_connection_t* conn);
62 | void (*audio_set_coverart)(void *cls, const void *buffer, int buflen, raop_connection_t* conn);
63 | void (*audio_remote_control_id)(void *cls, const char *dacp_id, const char *active_remote_header, raop_connection_t* conn);
64 | void (*audio_set_progress)(void *cls, unsigned int start, unsigned int curr, unsigned int end, raop_connection_t* conn);
65 | void (*audio_get_format)(void *cls, audio_format_info* info, raop_connection_t* conn);
66 | void (*video_report_size)(void *cls, float *width_source, float *height_source, float *width, float *height, raop_connection_t* conn);
67 | };
68 | typedef struct raop_callbacks_s raop_callbacks_t;
69 | raop_ntp_t *raop_ntp_init(raop_connection_t* conn, logger_t *logger, raop_callbacks_t *callbacks, const unsigned char *remote_addr, int remote_addr_len, unsigned short timing_rport);
70 |
71 | RAOP_API raop_t *raop_init(int max_clients, raop_callbacks_t *callbacks);
72 | RAOP_API void raop_set_log_level(raop_t *raop, int level);
73 | RAOP_API void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls);
74 | RAOP_API int raop_set_plist(raop_t *raop, const char *plist_item, const int value);
75 | RAOP_API void raop_set_port(raop_t *raop, unsigned short port);
76 | RAOP_API void raop_set_udp_ports(raop_t *raop, unsigned short port[3]);
77 | RAOP_API void raop_set_tcp_ports(raop_t *raop, unsigned short port[2]);
78 | RAOP_API unsigned short raop_get_port(raop_t *raop);
79 | RAOP_API void *raop_get_callback_cls(raop_t *raop);
80 | RAOP_API int raop_start(raop_t *raop, unsigned short *port);
81 | RAOP_API int raop_is_running(raop_t *raop);
82 | RAOP_API void raop_stop(raop_t *raop);
83 | RAOP_API void raop_set_dnssd(raop_t *raop, dnssd_t *dnssd);
84 | RAOP_API void raop_destroy(raop_t *raop);
85 |
86 | RAOP_API void raop_stop_conn(raop_connection_t* conn);
87 |
88 | #ifdef __cplusplus
89 | }
90 | #endif
91 | #endif
92 |
--------------------------------------------------------------------------------
/airplay/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 | #include "logger.h"
19 | #include "raop_rtp.h"
20 |
21 | typedef struct raop_buffer_s raop_buffer_t;
22 |
23 | typedef int (*raop_resend_cb_t)(void *opaque, unsigned short seqno, unsigned short count);
24 |
25 | raop_buffer_t *raop_buffer_init(logger_t *logger,
26 | const unsigned char *aeskey,
27 | const unsigned char *aesiv);
28 | int raop_buffer_enqueue(raop_buffer_t *raop_buffer, unsigned char *data, unsigned short datalen, uint64_t timestamp, int use_seqnum);
29 | void *raop_buffer_dequeue(raop_buffer_t *raop_buffer, unsigned int *length, uint64_t *timestamp, int no_resend);
30 | void raop_buffer_handle_resends(raop_buffer_t *raop_buffer, raop_resend_cb_t resend_cb, void *opaque);
31 | void raop_buffer_flush(raop_buffer_t *raop_buffer, int next_seq);
32 |
33 | int raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned char* output,
34 | unsigned int datalen, unsigned int *outputlen);
35 | void raop_buffer_destroy(raop_buffer_t *raop_buffer);
36 |
37 | #endif
38 |
--------------------------------------------------------------------------------
/airplay/raop_ntp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, modified by Florian Draschbacher,
3 | * All Rights Reserved.
4 | *
5 | * This library is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU Lesser General Public
7 | * License as published by the Free Software Foundation; either
8 | * version 2.1 of the License, or (at your option) any later version.
9 | *
10 | * This library is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 | * Lesser General Public License for more details.
14 | */
15 |
16 | #ifndef RAOP_NTP_H
17 | #define RAOP_NTP_H
18 |
19 | #include
20 | #include
21 | #include "logger.h"
22 |
23 | typedef struct raop_ntp_s raop_ntp_t;
24 |
25 |
26 | void raop_ntp_start(raop_ntp_t *raop_ntp, unsigned short *timing_lport, int max_ntp_timeouts);
27 |
28 | void raop_ntp_stop(raop_ntp_t *raop_ntp);
29 |
30 | unsigned short raop_ntp_get_port(raop_ntp_t *raop_ntp);
31 |
32 | void raop_ntp_destroy(raop_ntp_t *raop_rtp);
33 |
34 | uint64_t raop_ntp_timestamp_to_micro_seconds(uint64_t ntp_timestamp, bool account_for_epoch_diff);
35 |
36 | uint64_t raop_ntp_get_local_time(raop_ntp_t *raop_ntp);
37 | uint64_t raop_ntp_get_remote_time(raop_ntp_t *raop_ntp);
38 | uint64_t raop_ntp_convert_remote_time(raop_ntp_t *raop_ntp, uint64_t remote_time);
39 | uint64_t raop_ntp_convert_local_time(raop_ntp_t *raop_ntp, uint64_t local_time);
40 |
41 | #endif //RAOP_NTP_H
42 |
--------------------------------------------------------------------------------
/airplay/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 | #include "raop_ntp.h"
22 |
23 | #define RAOP_AESIV_LEN 16
24 | #define RAOP_AESKEY_LEN 16
25 | #define RAOP_PACKET_LEN 32768
26 |
27 | typedef struct raop_rtp_s raop_rtp_t;
28 |
29 | raop_rtp_t *raop_rtp_init(raop_connection_t* conn, logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote,
30 | int remotelen, const unsigned char *aeskey, const unsigned char *aesiv);
31 |
32 | void raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short control_rport,
33 | unsigned short *control_lport, unsigned short *data_lport);
34 |
35 | void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume);
36 | void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen);
37 | void raop_rtp_set_coverart(raop_rtp_t *raop_rtp, const char *data, int datalen);
38 | void raop_rtp_remote_control_id(raop_rtp_t *raop_rtp, const char *dacp_id, const char *active_remote_header);
39 | void raop_rtp_set_progress(raop_rtp_t *raop_rtp, unsigned int start, unsigned int curr, unsigned int end);
40 | void raop_rtp_flush(raop_rtp_t *raop_rtp, int next_seq);
41 | void raop_rtp_stop(raop_rtp_t *raop_rtp);
42 | int raop_rtp_is_running(raop_rtp_t *raop_rtp);
43 | void raop_rtp_destroy(raop_rtp_t *raop_rtp);
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/airplay/raop_rtp_mirror.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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_MIRROR_H
16 | #define RAOP_RTP_MIRROR_H
17 |
18 | #include
19 | #include "raop.h"
20 | #include "logger.h"
21 |
22 | typedef struct raop_rtp_mirror_s raop_rtp_mirror_t;
23 | typedef struct h264codec_s h264codec_t;
24 |
25 | raop_rtp_mirror_t *raop_rtp_mirror_init(raop_connection_t* conn, logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp,
26 | const unsigned char *remote, int remotelen, const unsigned char *aeskey);
27 | void raop_rtp_init_mirror_aes(raop_rtp_mirror_t *raop_rtp_mirror, uint64_t *streamConnectionID);
28 | void raop_rtp_start_mirror(raop_rtp_mirror_t *raop_rtp_mirror, int use_udp, unsigned short *mirror_data_lport, uint8_t show_client_FPS_data);
29 | void raop_rtp_mirror_stop(raop_rtp_mirror_t *raop_rtp_mirror);
30 | void raop_rtp_mirror_destroy(raop_rtp_mirror_t *raop_rtp_mirror);
31 | #endif //RAOP_RTP_MIRROR_H
32 |
--------------------------------------------------------------------------------
/airplay/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 |
--------------------------------------------------------------------------------
/airplay/stream.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 dsafa22, All Rights Reserved.
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 AIRPLAYSERVER_STREAM_H
16 | #define AIRPLAYSERVER_STREAM_H
17 |
18 | #include
19 | #include
20 |
21 | typedef struct{
22 | uint32_t sr;
23 | uint8_t ct;
24 | uint16_t spf;
25 | uint64_t audioFormat;
26 | uint8_t isMedia;
27 | uint8_t usingScreen;
28 | } audio_format_info;
29 |
30 | typedef struct {
31 | int nal_count;
32 | unsigned char *data;
33 | int data_len;
34 | uint64_t pts;
35 | } h264_decode_struct;
36 |
37 | typedef struct {
38 | unsigned char *data;
39 | int data_len;
40 | uint64_t pts;
41 | } aac_decode_struct;
42 |
43 | #endif //AIRPLAYSERVER_STREAM_H
44 |
--------------------------------------------------------------------------------
/airplay/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 | #else /* Use pthread library */
38 |
39 | #include
40 | #include
41 |
42 | #define sleepms(x) usleep((x)*1000)
43 |
44 | typedef pthread_t thread_handle_t;
45 |
46 | #define THREAD_RETVAL void *
47 | #define THREAD_CREATE(handle, func, arg) \
48 | if (pthread_create(&(handle), NULL, func, arg)) handle = 0
49 | #define THREAD_CANCEL(handle) pthread_cancel(handle)
50 | #define THREAD_JOIN(handle) pthread_join(handle, NULL)
51 |
52 | typedef pthread_mutex_t mutex_handle_t;
53 |
54 | typedef pthread_cond_t cond_handle_t;
55 |
56 | #define MUTEX_CREATE(handle) pthread_mutex_init(&(handle), NULL)
57 | #define MUTEX_LOCK(handle) pthread_mutex_lock(&(handle))
58 | #define MUTEX_UNLOCK(handle) pthread_mutex_unlock(&(handle))
59 | #define MUTEX_DESTROY(handle) pthread_mutex_destroy(&(handle))
60 |
61 | #define COND_CREATE(handle) pthread_cond_init(&(handle), NULL)
62 | #define COND_SIGNAL(handle) pthread_cond_signal(&(handle))
63 | #define COND_DESTROY(handle) pthread_cond_destroy(&(handle))
64 |
65 | #endif
66 |
67 | #endif /* THREADS_H */
68 |
--------------------------------------------------------------------------------
/airplay/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 | #include
19 |
20 | char *utils_strsep(char **stringp, const char *delim);
21 | int utils_read_file(char **dst, const char *pemstr);
22 | int utils_hwaddr_raop(char *str, int strlen, const char *hwaddr, int hwaddrlen);
23 | int utils_hwaddr_airplay(char *str, int strlen, const char *hwaddr, int hwaddrlen);
24 | char *utils_parse_hex(const char *str, int str_len, int *data_len);
25 | char *utils_data_to_string(const unsigned char *data, int datalen, int chars_per_line);
26 | char *utils_data_to_text(const char *data, int datalen);
27 | void ntp_timestamp_to_time(uint64_t ntp_timestamp, char *timestamp, size_t maxsize);
28 | void ntp_timestamp_to_seconds(uint64_t ntp_timestamp, char *timestamp, size_t maxsize);
29 | #endif
30 |
--------------------------------------------------------------------------------
/img/close.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/close.png
--------------------------------------------------------------------------------
/img/crop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/crop.png
--------------------------------------------------------------------------------
/img/display.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/display.png
--------------------------------------------------------------------------------
/img/opacity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/opacity.png
--------------------------------------------------------------------------------
/img/pause.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pause.png
--------------------------------------------------------------------------------
/img/pin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pin.png
--------------------------------------------------------------------------------
/img/pinned.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pinned.png
--------------------------------------------------------------------------------
/img/play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/play.png
--------------------------------------------------------------------------------
/img/pop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pop.png
--------------------------------------------------------------------------------
/img/pop_in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pop_in.png
--------------------------------------------------------------------------------
/img/pop_out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/pop_out.png
--------------------------------------------------------------------------------
/img/stop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/stop.png
--------------------------------------------------------------------------------
/img/uncrop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/uncrop.png
--------------------------------------------------------------------------------
/img/windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/img/windows.png
--------------------------------------------------------------------------------
/package.sh:
--------------------------------------------------------------------------------
1 | set -ex
2 |
3 | SRC_ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4 | cd $SRC_ROOT_DIR
5 |
6 | xcodebuild -alltargets archive
7 |
8 | APP_DIR="build/Release/PiP.app"
9 | PLIST="$APP_DIR/Contents/Info.plist"
10 |
11 | NAME=$(/usr/libexec/PlistBuddy -c "Print :CFBundleName" $PLIST)
12 | VERSION=$(/usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" $PLIST)
13 |
14 | dmgbuild -s settings.py -D app=$APP_DIR $NAME build/$NAME-$VERSION.dmg
15 |
--------------------------------------------------------------------------------
/pip/H264Decoder.h:
--------------------------------------------------------------------------------
1 | //
2 | // H264Decoder.h
3 | // PiP
4 | //
5 | // Created by Amit Verma on 25/04/22.
6 | // Copyright © 2022 boggyb. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | typedef void (^ReturnDecodedVideoDataBlock) (CVPixelBufferRef pixelBuffer);
13 |
14 | @interface H264Decoder : NSObject
15 |
16 | @property (nonatomic, copy) ReturnDecodedVideoDataBlock returnDataBlock;
17 | -(void)decode:(uint8_t*)data withLength:(size_t)length andReturnDecodedData:(ReturnDecodedVideoDataBlock)block;
18 | -(void)destroy;
19 | @end
20 |
--------------------------------------------------------------------------------
/pip/H264Decoder.m:
--------------------------------------------------------------------------------
1 | //
2 | // H264Decoder.m
3 | // PiP
4 | //
5 | // Created by Amit Verma on 25/04/22.
6 | // Copyright © 2022 boggyb. All rights reserved.
7 | //
8 |
9 | #import "H264Decoder.h"
10 |
11 | @interface H264Decoder(){
12 | uint8_t *mSPS, *mPPS;
13 | long mSPSSize, mPPSSize;
14 | VTDecompressionSessionRef mDecodeSession;
15 | CMFormatDescriptionRef mFormatDescription;
16 | bool should_reset;
17 | }
18 | @end
19 |
20 | @implementation H264Decoder
21 | - (instancetype)init {
22 | self = [super init];
23 | should_reset = false;
24 | return self;
25 | }
26 |
27 | void didDecompress(void *decompressionOutputRefCon, void *sourceFrameRefCon, OSStatus status, VTDecodeInfoFlags infoFlags, CVImageBufferRef pixelBuffer, CMTime presentationTimeStamp, CMTime presentationDuration){
28 | if(status != noErr) NSLog(@"didDecompress failed with code: %d", status);
29 | CVPixelBufferRef *outputPixelBuffer = (CVPixelBufferRef *)sourceFrameRefCon;
30 | *outputPixelBuffer = CVPixelBufferRetain(pixelBuffer);
31 | }
32 |
33 | -(void)decode:(uint8_t*)data withLength:(size_t)length andReturnDecodedData:(ReturnDecodedVideoDataBlock)block{
34 | self.returnDataBlock = block;
35 | uint32_t nalSize = (uint32_t)(length - 4);
36 | uint32_t *pNalSize = (uint32_t *)data;
37 | *pNalSize = CFSwapInt32HostToBig(nalSize);
38 |
39 | CVPixelBufferRef pixelBuffer = NULL;
40 | int nalType = data[4] & 0x1F;
41 | switch (nalType){
42 | case 0x07:
43 | should_reset = true;
44 | if(mSPS) free(mSPS);
45 | mSPSSize = length - 4;
46 | mSPS = malloc(mSPSSize);
47 | memcpy(mSPS, data + 4, mSPSSize);
48 | break;
49 | case 0x08:
50 | if(mPPS) free(mPPS);
51 | mPPSSize = length - 4;
52 | mPPS = malloc(mPPSSize);
53 | memcpy(mPPS, data + 4, mPPSSize);
54 | break;
55 | case 0x05:
56 | if(should_reset && mDecodeSession){
57 | VTDecompressionSessionInvalidate(mDecodeSession);
58 | CFRelease(mDecodeSession);
59 | mDecodeSession = NULL;
60 | }
61 | should_reset = false;
62 | [self initVideoToolBox];
63 | default:{
64 | CMBlockBufferRef blockBuffer = NULL;
65 | OSStatus status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault, data, length, kCFAllocatorNull, NULL, 0, length, 0, &blockBuffer);
66 | if(status == kCMBlockBufferNoErr) {
67 | CMSampleBufferRef sampleBuffer = NULL;
68 | const size_t sampleSizeArray[] = {length};
69 | status = CMSampleBufferCreateReady(kCFAllocatorDefault, blockBuffer, mFormatDescription, 1, 0, NULL, 1, sampleSizeArray, &sampleBuffer);
70 | if(status == kCMBlockBufferNoErr && sampleBuffer) {
71 | OSStatus decodeStatus = VTDecompressionSessionDecodeFrame(mDecodeSession, sampleBuffer, 0, &pixelBuffer, NULL);
72 | if(decodeStatus != noErr) NSLog(@"decode failed status=%d", decodeStatus);
73 | CFRelease(sampleBuffer);
74 | }
75 | CFRelease(blockBuffer);
76 | }
77 | break;
78 | }
79 | }
80 | if(!pixelBuffer) return;
81 | self.returnDataBlock(pixelBuffer);
82 | CVPixelBufferRelease(pixelBuffer);
83 | }
84 |
85 | -(void)initVideoToolBox{
86 | if(mDecodeSession) return;
87 | const uint8_t* parameterSetPointers[2] = {mSPS, mPPS};
88 | const size_t parameterSetSizes[2] = {mSPSSize, mPPSSize};
89 | OSStatus status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault, 2, parameterSetPointers, parameterSetSizes, 4, &mFormatDescription);
90 | if(status != noErr){
91 | NSLog(@"CMVideoFormatDescriptionCreateFromH264ParameterSets failed with code: %d", status);
92 | return;
93 | }
94 | VTDecompressionOutputCallbackRecord callBackRecord;
95 | callBackRecord.decompressionOutputCallback = didDecompress;
96 | callBackRecord.decompressionOutputRefCon = NULL;
97 |
98 | status = VTDecompressionSessionCreate(kCFAllocatorDefault, mFormatDescription, NULL, NULL, &callBackRecord, &mDecodeSession);
99 | if(status != noErr){//kVTVideoDecoderBadDataErr
100 | NSLog(@"VTDecompressionSessionCreate failed with code: %d", status);
101 | }
102 | }
103 |
104 | -(void)destroy{
105 | if(mDecodeSession) {
106 | VTDecompressionSessionInvalidate(mDecodeSession);
107 | CFRelease(mDecodeSession);
108 | mDecodeSession = NULL;
109 | }
110 |
111 | if(mFormatDescription) {
112 | CFRelease(mFormatDescription);
113 | mFormatDescription = NULL;
114 | }
115 |
116 | if(mSPS) free(mSPS);
117 | if(mPPS) free(mPPS);
118 | mSPS = mPPS = NULL;
119 | mSPSSize = mPPSSize = 0;
120 | }
121 |
122 | @end
123 |
124 |
125 |
--------------------------------------------------------------------------------
/pip/Media.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "512x512",
5 | "idiom" : "mac",
6 | "filename" : "pip_512p.png",
7 | "scale" : "1x"
8 | }
9 | ],
10 | "info" : {
11 | "version" : 1,
12 | "author" : "xcode"
13 | }
14 | }
--------------------------------------------------------------------------------
/pip/Media.xcassets/AppIcon.appiconset/pip_512p.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/amitv87/PiP/5e8f31c5694d3013c12b5288986d1e1d96f93f42/pip/Media.xcassets/AppIcon.appiconset/pip_512p.png
--------------------------------------------------------------------------------
/pip/Media.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/pip/audioPlayer.h:
--------------------------------------------------------------------------------
1 | //
2 | // audioPlayer.h
3 | // PiP
4 | //
5 | // Created by Amit Verma on 25/04/22.
6 | // Copyright © 2022 boggyb. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | @interface AudioPlayer : NSObject
14 | -(void)setInputFormat:(UInt32)format withSampleRate:(UInt32)sampleRate andChannels:(UInt32)channelCount andSPF:(UInt32)spf;
15 | -(void)setVolume:(float)volume;
16 | -(void)decode:(uint8_t*)data andLength:(size_t)length;
17 | -(void)destroy;
18 | @end
19 |
20 | NS_ASSUME_NONNULL_END
21 |
--------------------------------------------------------------------------------
/pip/cgs.h:
--------------------------------------------------------------------------------
1 | //
2 | // cgs.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 06/04/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef cgs_h
10 | #define cgs_h
11 |
12 | #include
13 |
14 | #define kCPSAllWindows 0x100
15 | #define kCPSUserGenerated 0x200
16 | #define kCPSNoWindows 0x400
17 |
18 | typedef int CGSConnectionID;
19 |
20 | typedef enum {
21 | kCGSWindowCaptureNominalResolution = (1 << 9),
22 | kCGSCaptureIgnoreGlobalClipShape = (1 << 11),
23 | } CGSWindowCaptureOptions;
24 |
25 | typedef enum {
26 | CGSSpaceIncludesCurrent = 1 << 0,
27 | CGSSpaceIncludesOthers = 1 << 1,
28 | CGSSpaceIncludesUser = 1 << 2,
29 | CGSSpaceVisible = 1 << 16,
30 | kCGSCurrentSpaceMask = CGSSpaceIncludesUser | CGSSpaceIncludesCurrent,
31 | kCGSOtherSpacesMask = CGSSpaceIncludesOthers | CGSSpaceIncludesCurrent,
32 | kCGSAllSpacesMask = CGSSpaceIncludesUser | CGSSpaceIncludesOthers | CGSSpaceIncludesCurrent,
33 | KCGSAllVisibleSpacesMask = CGSSpaceVisible | kCGSAllSpacesMask,
34 | } CGSSpaceMask;
35 |
36 | CGSConnectionID CGSMainConnectionID(void);
37 |
38 | CGError SLPSPostEventRecordTo(ProcessSerialNumber *psn, uint8_t *bytes);
39 | CGError CGSGetConnectionPSN(CGSConnectionID cid, ProcessSerialNumber *psn);
40 | CGError CGSGetWindowOwner(CGSConnectionID cid, CGWindowID wid, CGSConnectionID *ownerCid);
41 | CGError CGSConnectionGetPID(CGSConnectionID cid, pid_t *pid, CGSConnectionID ownerCid);
42 | CGError SLPSSetFrontProcessWithOptions(ProcessSerialNumber *psn, CGWindowID wid, uint32_t mode);
43 |
44 | OSStatus CGSGetConnectionIDForPSN(CGSConnectionID cid, ProcessSerialNumber *psn, CGSConnectionID *out);
45 |
46 | CFArrayRef CGSCopySpacesForWindows(CGSConnectionID cid, CGSSpaceMask mask, CFArrayRef windowIDs);
47 | CFArrayRef CGSHWCaptureWindowList(CGSConnectionID, CGWindowID* windowList, int count, CGSWindowCaptureOptions);
48 |
49 | #endif /* cgs_h */
50 |
--------------------------------------------------------------------------------
/pip/common.h:
--------------------------------------------------------------------------------
1 | //
2 | // common.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 09/12/17.
6 | // Copyright © 2017 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef common_h
10 | #define common_h
11 |
12 | static const int kMinSize = 180;
13 | static const int kStartSize = 400;
14 |
15 | #endif /* common_h */
16 |
--------------------------------------------------------------------------------
/pip/imageRenderer.h:
--------------------------------------------------------------------------------
1 | //
2 | // imageRenderer.h
3 | // PiP
4 | //
5 | // Created by Amit Verma on 5/14/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef imageRenderer_h
10 | #define imageRenderer_h
11 |
12 | #import
13 |
14 | @protocol ImageRendererDelegate
15 | - (void)onResize:(CGSize)size andAspectRatio:(CGSize) ar;
16 | @end
17 |
18 | @protocol ImageRenderer
19 | @property (nonatomic,strong) CIContext *context;
20 | @property (nonatomic,strong,readonly) NSView *view;
21 | @property (nonatomic,strong) id delegate;
22 | - (instancetype)init:(BOOL)hidpi;
23 | - (NSRect)cropRect;
24 | - (void)setScale:(float) scale;
25 | - (void)setCropRect:(NSRect) rect;
26 | - (void)renderImage:(CIImage *)image;
27 | @end
28 |
29 | @interface MetalRenderer : NSObject
30 | //@property (nonatomic,strong,readonly) MTKView *view;
31 | @end
32 |
33 | @interface OpenGLRenderer : NSObject
34 | //@property (nonatomic,strong,readonly) NSOpenGLView *view;
35 | @end
36 |
37 | #endif /* imageRenderer_h */
38 |
--------------------------------------------------------------------------------
/pip/imageView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ImageView.h
3 | // PiP
4 | //
5 | // Created by Amit Verma on 5/14/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef imageView_h
10 | #define imageView_h
11 |
12 | #import "imageRenderer.h"
13 |
14 | @interface ImageView : NSView
15 | @property (nonatomic,strong) id renderer;
16 | - (void)setImage:(CIImage *)image;
17 | @end
18 |
19 | #endif
20 |
--------------------------------------------------------------------------------
/pip/imageView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ImageView.m
3 | // PiP
4 | //
5 | // Created by Amit Verma on 5/14/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #import "imageView.h"
10 |
11 | @implementation ImageView
12 |
13 | - (instancetype)initWithFrame:(CGRect)frame {
14 | self = [super initWithFrame:frame];
15 | self.autoresizingMask = NSViewHeightSizable | NSViewWidthSizable | NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
16 | return self;
17 | }
18 |
19 | - (void)setRenderer:(id)renderer {
20 | if(_renderer){
21 | [_renderer renderImage:nil];
22 | [_renderer.view removeFromSuperview];
23 | }
24 | _renderer = renderer;
25 | if(!_renderer) return;
26 | [self addSubview:_renderer.view];
27 | _renderer.view.frame = CGRectIntegral(self.bounds);
28 | _renderer.view.autoresizingMask = NSViewHeightSizable | NSViewWidthSizable | NSViewMinXMargin | NSViewMaxXMargin | NSViewMinYMargin | NSViewMaxYMargin;
29 | }
30 |
31 | - (void)setImage:(CIImage *)image {
32 | [self.renderer renderImage:image];
33 | }
34 |
35 | @end
36 |
--------------------------------------------------------------------------------
/pip/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Icon file
6 | AppIcon
7 | CFBundleVersion
8 | 21
9 | CFBundleShortVersionString
10 | 2.70
11 | CFBundleExecutable
12 | $(EXECUTABLE_NAME)
13 | CFBundleIdentifier
14 | $(PRODUCT_BUNDLE_IDENTIFIER)
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | NSHighResolutionCapable
18 | True
19 |
20 |
21 |
--------------------------------------------------------------------------------
/pip/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // pip
4 | //
5 | // Created by Amit Verma on 02/12/17.
6 | // Copyright © 2017 boggyb. All rights reserved.
7 | //
8 |
9 | #import "window.h"
10 | #import "preferences.h"
11 | #import
12 |
13 | extern int windowCount;
14 |
15 | #define ADD_SEP() [menu addItem:[NSMenuItem separatorItem]]
16 | #define INIT_MENU(title) {menu = [[NSMenu alloc] initWithTitle:title]; NSMenuItem* item = [[NSMenuItem alloc] init];[item setSubmenu:menu];[menubar addItem:item];}
17 | #define ADD_ITEM(title, sel, key) [menu addItem:[[NSMenuItem alloc] initWithTitle:title action:@selector(sel) keyEquivalent:key]]
18 |
19 | #define ADD_ITEM_MASK(title, sel, key, mask){ \
20 | NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:title action:@selector(sel) keyEquivalent:key]; \
21 | item.keyEquivalentModifierMask = mask; \
22 | [menu addItem:item]; \
23 | }
24 |
25 | #define XSTRINGIFY(s) #s
26 | #define STRINGIFY(s) XSTRINGIFY(s)
27 |
28 | #define ADD_SCALE_ITEM(scale) [self addScaleMenuItemWithTitle:@"Scale " STRINGIFY(scale) keyEquivalent:@ STRINGIFY(scale) mask:NO andScale:100 * scale toMenu:menu];
29 | #define ADD_SCALE_ITEM_INVERSE(scale) [self addScaleMenuItemWithTitle:@"Scale 1/" STRINGIFY(scale) keyEquivalent:@ STRINGIFY(scale) mask:YES andScale:100 / scale toMenu:menu];
30 |
31 | @interface MyApplicationDelegate : NSObject {
32 | NSApplication* app;
33 | NSMenuItem* windowMenuItem;
34 | boolean_t clickThroughState;
35 | }
36 | @end
37 |
38 | @implementation MyApplicationDelegate
39 | -(id)initWithApp:(NSApplication*) application{
40 | self = [super init];
41 | app = application;
42 | clickThroughState = false;
43 |
44 | NSMenu* menu;
45 | NSMenu* menubar = [[NSMenu alloc] init];
46 | NSString* appName = [[NSProcessInfo processInfo] processName];
47 |
48 | INIT_MENU(appName);
49 | ADD_ITEM([@"About " stringByAppendingString:appName], orderFrontStandardAboutPanel:, @"");
50 | ADD_SEP();
51 | ADD_ITEM(@"Preferences", showPreferencePanel:, @",");
52 | ADD_SEP();
53 | ADD_ITEM([@"Hide " stringByAppendingString:appName], hideAll, @"h");
54 | ADD_ITEM([@"Quit " stringByAppendingString:appName], terminate:, @"q");
55 |
56 | INIT_MENU(@"File");
57 | ADD_ITEM(@"New", newWindow, @"n");
58 | ADD_ITEM(@"Click Through", clickThrough:, @"c");
59 | ADD_ITEM(@"Close", performClose:, @"w");
60 |
61 | INIT_MENU(@"Window");
62 | ADD_SCALE_ITEM(1);
63 | ADD_SCALE_ITEM(2);
64 | ADD_SCALE_ITEM(3);
65 | ADD_SEP();
66 | ADD_SCALE_ITEM_INVERSE(2);
67 | ADD_SCALE_ITEM_INVERSE(3);
68 | ADD_SCALE_ITEM_INVERSE(4);
69 | ADD_SEP();
70 | ADD_ITEM_MASK(@"Zoom", performZoom:, @"z", NSEventModifierFlagCommand | NSEventModifierFlagOption);
71 | ADD_ITEM(@"Fullscreen", toggleFullScreen:, @"f");
72 | ADD_ITEM(@"Minimize", performMiniaturize:, @"m");
73 | ADD_ITEM(@"Always on top", toggleFloat, @"a");
74 | ADD_ITEM(@"Join all spaces", togglePin, @"j");
75 | ADD_ITEM(@"Bring All to Front", arrangeInFront:, @"");
76 | ADD_ITEM(@"Toggle Native PiP", toggleNativePip, @"p");
77 |
78 | [app setMainMenu:menubar];
79 |
80 | [app setDelegate:self];
81 | return self;
82 | }
83 |
84 | -(void) addScaleMenuItemWithTitle:(NSString*) title keyEquivalent:(NSString*) key mask:(BOOL) flag andScale:(NSInteger) scale toMenu:(NSMenu*) windowMenu{
85 | NSMenuItem* scaleItem = [windowMenu addItemWithTitle:title action:@selector(setScale:) keyEquivalent:key];
86 | [scaleItem setTag:scale];
87 | if(flag) [scaleItem setKeyEquivalentModifierMask:NSEventModifierFlagCommand | NSEventModifierFlagOption];
88 | }
89 |
90 | - (void) run{
91 | [app run];
92 | }
93 |
94 | - (void) getActiveWindow: (void (^)(Window* window))cb{
95 | NSWindow* currentWindow = (NSWindow*)[app keyWindow];
96 | if(!currentWindow || ![currentWindow isKindOfClass:[Window class]]){
97 | currentWindow = NULL;
98 | for(NSWindow* window in [app windows]){
99 | if([window isKindOfClass:[Window class]]){
100 | currentWindow = (Window*)window;
101 | break;
102 | }
103 | }
104 | }
105 | if(currentWindow) cb((Window*)currentWindow);
106 | }
107 |
108 | - (NSWindow*) newWindow{
109 | NSWindow* window = [[Window alloc] initWithAirplay: false andTitle:nil];
110 | [window makeKeyAndOrderFront:self];
111 | [window setIgnoresMouseEvents:clickThroughState];
112 | return window;
113 | }
114 |
115 | - (void) hideAll{
116 | [app hide:self];
117 | }
118 |
119 | -(void) clickThrough:(id)sender{
120 | NSMenuItem* item = (NSMenuItem*)sender;
121 | clickThroughState = !item.state;
122 | [item setState:clickThroughState];
123 | for(NSWindow* window in [app windows]){
124 | if([window isKindOfClass:[Window class]]) [window setIgnoresMouseEvents:clickThroughState];
125 | }
126 | }
127 |
128 | -(void)applicationDidFinishLaunching:(NSNotification *)notification{
129 | [app setActivationPolicy:NSApplicationActivationPolicyRegular];
130 | [app activateIgnoringOtherApps:YES];
131 | [self newWindow];
132 | // [self showPreferencePanel:self];
133 | #ifndef NO_AIRPLAY
134 | if([(NSNumber*)getPref(@"airplay") intValue] > 0) airplay_receiver_start();
135 | #endif
136 | }
137 |
138 | - (void)applicationWillTerminate:(NSNotification *)notification{
139 | NSLog(@"applicationWillTerminate");
140 | #ifndef NO_AIRPLAY
141 | airplay_receiver_stop();
142 | #endif
143 | }
144 |
145 | - (void)showPreferencePanel:(id)sender{
146 | if(global_pref) return;
147 | global_pref = [[Preferences alloc] init];
148 | [global_pref makeKeyAndOrderFront:self];
149 | }
150 |
151 | -(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender{
152 | return false;
153 | }
154 |
155 | @end
156 |
157 | int main(int argc, const char * argv[]) {
158 | [[[MyApplicationDelegate alloc] initWithApp:[NSApplication sharedApplication]] run];
159 | return 0;
160 | }
161 |
--------------------------------------------------------------------------------
/pip/metalRenderer.m:
--------------------------------------------------------------------------------
1 | //
2 | // metalRenderer.m
3 | // PiP
4 | //
5 | // Created by Amit Verma on 5/14/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #import "common.h"
10 | #import "imageRenderer.h"
11 |
12 | #import
13 | #import
14 |
15 | @interface MetalRenderer ()
16 | @property (nonatomic,strong) MTKView *view;
17 | @property (nonatomic,strong) CIImage *image;
18 | @property (nonatomic,strong) id device;
19 | @property (nonatomic,strong) id commandQueue;
20 | @end
21 |
22 | @implementation MetalRenderer{
23 | NSRect cropRect;
24 | float imageScale;
25 | CGColorSpaceRef colorspace;
26 | }
27 |
28 | @synthesize context;
29 | @synthesize delegate;
30 |
31 | - (instancetype)init:(BOOL)hidpi{
32 | self = [super init];
33 | self.image = nil;
34 | self.device = MTLCreateSystemDefaultDevice();
35 | self.view = [[MTKView alloc] initWithFrame:CGRectZero device:self.device];
36 | self.view.clearColor = MTLClearColorMake(0, 0, 0, 0);
37 | self.view.delegate = self;
38 | self.view.framebufferOnly = NO;
39 | self.view.autoResizeDrawable = true;
40 | self.view.enableSetNeedsDisplay = YES;
41 | self.view.wantsBestResolutionOpenGLSurface = hidpi;
42 | colorspace = CGColorSpaceCreateDeviceRGB();
43 | self.context = [CIContext contextWithMTLDevice:self.device options:@{kCIContextWorkingColorSpace: (__bridge id)colorspace,}];
44 | self.commandQueue = [self.device newCommandQueue];
45 |
46 | imageScale = 0;
47 | cropRect = CGRectZero;
48 | return self;
49 | }
50 |
51 | - (void)dealloc{
52 | CGColorSpaceRelease(colorspace);
53 | }
54 |
55 | - (void)setCropRect:(NSRect) rect{
56 | if(!self.image) return;
57 | float scale = self.image.extent.size.width / self.view.frame.size.width;
58 | cropRect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(scale, scale));
59 | }
60 |
61 | - (void)drawInMTKView:(MTKView *)view {
62 | if(!self.image) return;
63 | id outputTexture = self.view.currentDrawable.texture;
64 | if (!outputTexture) return;
65 |
66 | CIImage* image = self.image;
67 |
68 | NSRect bounds = {.size = image.extent.size};
69 | NSSize frameSize = self.view.frame.size;
70 | float hidpi_scale = self.view.wantsBestResolutionOpenGLSurface ? self.view.window.backingScaleFactor : 1;
71 |
72 | if(cropRect.size.width * cropRect.size.height != 0) bounds = cropRect;
73 | bounds = CGRectApplyAffineTransform(bounds, CGAffineTransformMakeScale(1.0/hidpi_scale, 1.0/hidpi_scale));
74 |
75 | NSSize imageSize = bounds.size;
76 |
77 | NSSize availSize = self.view.window.screen.visibleFrame.size;
78 | float frameAspectRatio = frameSize.width / frameSize.height;
79 | float imageAspectRatio = imageSize.width / imageSize.height;
80 | float arr = imageAspectRatio / frameAspectRatio;
81 |
82 | NSSize targetSize = frameSize;
83 | if(imageScale){
84 | targetSize.width = imageScale * imageSize.width;
85 | targetSize.height = imageScale * imageSize.height;
86 | imageScale = 0;
87 | arr = 2;
88 | }
89 | else targetSize.height = targetSize.width / imageAspectRatio;
90 |
91 | if(targetSize.width > availSize.width || targetSize.height > availSize.height){
92 | arr = 2;
93 | NSSize size;
94 | size.width = fmin(availSize.height * imageAspectRatio, availSize.width);
95 | size.height = fmin(availSize.width / imageAspectRatio, availSize.height);
96 | targetSize = size;
97 | }
98 |
99 | if(arr < 0.99 || arr > 1.01) [self.delegate onResize:targetSize andAspectRatio:targetSize];
100 |
101 | float scale = targetSize.width / (imageSize.width / hidpi_scale);
102 |
103 | self.view.drawableSize = CGSizeApplyAffineTransform(bounds.size, CGAffineTransformMakeScale(hidpi_scale, hidpi_scale));
104 | bounds = CGRectApplyAffineTransform(bounds, CGAffineTransformMakeScale(scale, scale));
105 |
106 | // if(targetSize.width < imageSize.width){
107 | scale /= hidpi_scale;
108 | image = [image imageByApplyingTransform:CGAffineTransformMakeScale(scale, scale)];
109 | self.view.drawableSize = bounds.size;
110 | // }
111 |
112 | id commandBuffer = [self.commandQueue commandBuffer];
113 | [self.context render:image toMTLTexture:outputTexture commandBuffer:commandBuffer bounds:bounds colorSpace:colorspace];
114 | [commandBuffer presentDrawable:self.view.currentDrawable];
115 | [commandBuffer commit];
116 | }
117 |
118 | - (void)mtkView:(MTKView *)view drawableSizeWillChange:(CGSize)size {}
119 |
120 | - (void)renderImage:(CIImage *)image {
121 | self.image = image;
122 | if(self.image) self.view.needsDisplay = YES;
123 | else{
124 | imageScale = 0;
125 | cropRect = CGRectZero;
126 | }
127 | }
128 |
129 | - (void)setScale:(float)scale {
130 | if(!self.image) return;
131 | imageScale = scale / 100;
132 | self.view.needsDisplay = YES;
133 | }
134 |
135 | - (NSRect)cropRect{
136 | return self->cropRect;
137 | }
138 |
139 |
140 | @end
141 |
--------------------------------------------------------------------------------
/pip/openGLRenderer.m:
--------------------------------------------------------------------------------
1 | //
2 | // openGLRenderer.m
3 | // PiP
4 | //
5 | // Created by Amit Verma on 5/14/20.
6 | // Copyright © 2020 boggyb. All rights reserved.
7 | //
8 |
9 | #import "imageRenderer.h"
10 | #import
11 | #import
12 |
13 | @class GLView;
14 |
15 | @protocol OpenGLRenderDelegate
16 | - (void)openGLView:(GLView *)view drawRect:(CGRect)rect;
17 | @end
18 |
19 | @interface GLView : NSOpenGLView
20 | @property (nonatomic,weak) id renderDelegate;
21 | @end
22 |
23 | @implementation GLView
24 | - (void)drawRect:(NSRect)rect {
25 | [self.renderDelegate openGLView:self drawRect:rect];
26 | }
27 | -(BOOL) isOpaque{
28 | return NO;
29 | }
30 | @end
31 |
32 | @interface OpenGLRenderer ()
33 | @property (nonatomic,strong) CIImage *image;
34 | @property (nonatomic,strong) NSOpenGLView *view;
35 | @end
36 |
37 | static CIContext* ciContext = nil;
38 | static NSOpenGLContext* openGLContext = nil;
39 |
40 | static NSOpenGLContext* getGLContext(){
41 | if(!openGLContext) openGLContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil];
42 | return openGLContext;
43 | }
44 |
45 | static CIContext* getCIContext(){
46 | if(!ciContext) ciContext = [CIContext contextWithCGLContext:openGLContext.CGLContextObj pixelFormat:nil colorSpace:nil options:nil];
47 | return ciContext;
48 | }
49 |
50 | @implementation OpenGLRenderer{
51 | NSRect cropRect;
52 | float imageScale;
53 | }
54 |
55 | @synthesize context;
56 | @synthesize delegate;
57 |
58 | - (instancetype)init:(BOOL)hidpi{
59 | self = [super init];
60 | cropRect = CGRectZero;
61 | GLView *openGLView = [[GLView alloc] initWithFrame:CGRectZero pixelFormat:[NSOpenGLView defaultPixelFormat]];
62 | openGLView.renderDelegate = self;
63 | self.view = openGLView;
64 | self.view.openGLContext = getGLContext();
65 | self.view.wantsBestResolutionOpenGLSurface = hidpi;
66 | self.context = getCIContext();
67 | return self;
68 | }
69 |
70 | - (void)setCropRect:(NSRect) rect{
71 | if(!self.image) return;
72 | float scale = self.image.extent.size.width / self.view.frame.size.width;
73 | cropRect = CGRectApplyAffineTransform(rect, CGAffineTransformMakeScale(scale, scale));
74 | }
75 |
76 | - (void)openGLView:(GLView *)view drawRect:(CGRect)rect {
77 | if(!self.image) return;
78 |
79 | NSSize frameSize = self.view.frame.size;
80 | NSSize targetSize = frameSize;
81 | float hidpi_scale = self.view.wantsBestResolutionOpenGLSurface ? self.view.window.backingScaleFactor : 1;
82 |
83 | NSSize imageSize = CGSizeZero;
84 | if(cropRect.size.width * cropRect.size.height != 0) imageSize = CGSizeApplyAffineTransform(cropRect.size, CGAffineTransformMakeScale(1.0/hidpi_scale, 1.0/hidpi_scale));
85 | else imageSize = CGSizeApplyAffineTransform(self.image.extent.size, CGAffineTransformMakeScale(1.0/hidpi_scale, 1.0/hidpi_scale));
86 |
87 | NSSize availSize = self.view.window.screen.visibleFrame.size;
88 | float frameAspectRatio = frameSize.width / frameSize.height;
89 | float imageAspectRatio = imageSize.width / imageSize.height;
90 | float arr = imageAspectRatio / frameAspectRatio;
91 |
92 | if(imageScale){
93 | targetSize.width = imageScale * imageSize.width;
94 | targetSize.height = imageScale * imageSize.height;
95 | imageScale = 0;
96 | arr = 2;
97 | }
98 | else targetSize.height = targetSize.width / imageAspectRatio;
99 |
100 | if(targetSize.width > availSize.width || targetSize.height > availSize.height){
101 | arr = 2;
102 | NSSize size;
103 | size.width = fmin(availSize.height * imageAspectRatio, availSize.width);
104 | size.height = fmin(availSize.width / imageAspectRatio, availSize.height);
105 | targetSize = size;
106 | }
107 |
108 | if(arr < 0.99 || arr > 1.01) [self.delegate onResize:targetSize andAspectRatio:targetSize];
109 |
110 | NSRect fromRect = cropRect.size.width * cropRect.size.height == 0 ? (NSRect){.size = self.image.extent.size} : cropRect;
111 |
112 | NSRect inRect = {.size = targetSize};
113 |
114 | glMatrixMode(GL_PROJECTION);
115 | glLoadIdentity();
116 |
117 | glViewport(0, 0, targetSize.width * hidpi_scale, targetSize.height * hidpi_scale);
118 | glOrtho(0, targetSize.width, 0, targetSize.height, -1, 1);
119 |
120 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
121 | [self.context drawImage:self.image inRect:inRect fromRect:fromRect];
122 | glFlush();
123 | }
124 |
125 | - (void)renderImage:(CIImage *)image {
126 | self.image = image;
127 | if(self.image) self.view.needsDisplay = YES;
128 | else{
129 | imageScale = 0;
130 | cropRect = CGRectZero;
131 | }
132 | }
133 |
134 | - (void)setScale:(float)scale {
135 | if(!self.image) return;
136 | imageScale = scale / 100;
137 | self.view.needsDisplay = YES;
138 | }
139 |
140 | - (NSRect)cropRect{
141 | return self->cropRect;
142 | }
143 |
144 | @end
145 |
--------------------------------------------------------------------------------
/pip/pip.h:
--------------------------------------------------------------------------------
1 | //
2 | // pip.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 04/08/18.
6 | // Copyright © 2018 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef pip_h
10 | #define pip_h
11 |
12 | #import
13 |
14 | @class PIPViewController;
15 |
16 | @protocol PIPViewControllerDelegate
17 | @optional
18 | - (BOOL)pipShouldClose:(PIPViewController *)pip;
19 | - (void)pipActionStop:(PIPViewController *)pip;
20 | - (void)pipActionPause:(PIPViewController *)pip;
21 | - (void)pipActionPlay:(PIPViewController *)pip;
22 | - (void)pipActionReturn:(PIPViewController *)pip;
23 | - (void)pipDidClose:(PIPViewController *)pip;
24 | - (void)pipWillClose:(PIPViewController *)pip;
25 | @end
26 |
27 | @interface PIPViewController : NSViewController
28 | @property (nonatomic) bool playing;
29 | @property (nonatomic) NSSize aspectRatio;
30 | @property (nonatomic) bool userCanResize;
31 | @property (nonatomic) NSRect replacementRect;
32 | @property (nonatomic, weak) NSWindow *replacementWindow;
33 | @property (nonatomic, weak) id delegate;
34 |
35 | - (void)presentViewControllerAsPictureInPicture:(NSViewController *)viewController;
36 |
37 | @end
38 |
39 | #endif /* pip_h */
40 |
--------------------------------------------------------------------------------
/pip/preferences.h:
--------------------------------------------------------------------------------
1 | //
2 | // preferences.h
3 | // PiP
4 | //
5 | // Created by Amit Verma on 28/04/22.
6 | // Copyright © 2022 boggyb. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | NS_ASSUME_NONNULL_BEGIN
12 |
13 | typedef enum{
14 | DisplayRendererTypeMetal,
15 | DisplayRendererTypeOpenGL,
16 | } DisplayRendererType;
17 |
18 | NSObject* getPref(NSString* key);
19 | NSObject* getPrefOption(NSString* key);
20 | void setPref(NSString* key, NSObject* val);
21 |
22 | @interface Preferences : NSPanel
23 |
24 | @end
25 |
26 | extern Preferences* global_pref;
27 |
28 | NS_ASSUME_NONNULL_END
29 |
--------------------------------------------------------------------------------
/pip/receiver.h:
--------------------------------------------------------------------------------
1 | //
2 | // receiver.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 30/04/22.
6 | // Copyright © 2022 boggyb. All rights reserved.
7 | //
8 | #ifndef NO_AIRPLAY
9 |
10 | #ifndef receiver_h
11 | #define receiver_h
12 |
13 | #include "raop.h"
14 |
15 | void airplay_receiver_stop(void);
16 | void airplay_receiver_start(void);
17 | void airplay_receiver_session_stop(raop_connection_t* conn);
18 |
19 | #endif /* receiver_h */
20 |
21 | #endif
22 |
--------------------------------------------------------------------------------
/pip/selectionView.h:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionView.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 05/12/17.
6 | // Copyright © 2017 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef SelectionView_h
10 | #define SelectionView_h
11 |
12 | #import
13 | #import
14 |
15 | @protocol SelectionViewDelegate
16 | - (void) onSelcetion:(NSRect) rect;
17 | @end
18 |
19 | @interface SelectionView : NSView{}
20 | @property (nonatomic) NSPoint endPoint;
21 | @property (nonatomic) NSPoint startPoint;
22 | @property (nonatomic) id delegate;
23 | @property (nonatomic, strong) CAShapeLayer *shapeLayer;
24 | @end
25 |
26 | #endif /* SelectionView_h */
27 |
--------------------------------------------------------------------------------
/pip/selectionView.m:
--------------------------------------------------------------------------------
1 | //
2 | // SelectionView.m
3 | // pip
4 | //
5 | // Created by Amit Verma on 05/12/17.
6 | // Copyright © 2017 boggyb. All rights reserved.
7 | //
8 |
9 | #import "selectionView.h"
10 |
11 | @implementation SelectionView
12 |
13 | #define NSColorFromRGB(rgbValue) [NSColor colorWithCalibratedRed:((float)((rgbValue & 0xFF000000) >> 16))/255.0 green:((float)((rgbValue & 0xFF0000) >> 8))/255.0 blue:((float)(rgbValue & 0xFF00))/255.0 alpha:((float)(rgbValue & 0xFF))/255.0]
14 |
15 | - (void)mouseDown:(NSEvent *)theEvent{
16 | self.startPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
17 |
18 | self.shapeLayer = [CAShapeLayer layer];
19 | self.shapeLayer.lineWidth = 1.0;
20 | self.shapeLayer.shadowOpacity = 0.5;
21 |
22 | self.shapeLayer.strokeColor = [[NSColor grayColor] CGColor];
23 | self.shapeLayer.fillColor = [NSColorFromRGB(0x00000044) CGColor];
24 | self.shapeLayer.shadowColor = [[NSColor whiteColor] CGColor];
25 | self.shapeLayer.lineDashPattern = @[@10, @10];
26 | [self.layer addSublayer:self.shapeLayer];
27 |
28 | CABasicAnimation *dashAnimation;
29 | dashAnimation = [CABasicAnimation animationWithKeyPath:@"lineDashPhase"];
30 | [dashAnimation setFromValue:@0.0f];
31 | [dashAnimation setToValue:@15.0f];
32 | [dashAnimation setDuration:0.75f];
33 | [dashAnimation setRepeatCount:HUGE_VALF];
34 | [self.shapeLayer addAnimation:dashAnimation forKey:@"linePhase"];
35 | }
36 |
37 | - (void)mouseDragged:(NSEvent *)theEvent{
38 | if(!NSPointInRect([theEvent locationInWindow], [self frame])) return;
39 | NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil];
40 |
41 | self.endPoint = point;
42 |
43 | CGMutablePathRef path = CGPathCreateMutable();
44 | CGPathMoveToPoint(path, NULL, self.startPoint.x, self.startPoint.y);
45 | CGPathAddLineToPoint(path, NULL, self.startPoint.x, point.y);
46 | CGPathAddLineToPoint(path, NULL, point.x, point.y);
47 | CGPathAddLineToPoint(path, NULL, point.x, self.startPoint.y);
48 | CGPathCloseSubpath(path);
49 |
50 | self.shapeLayer.path = path;
51 | CGPathRelease(path);
52 | }
53 |
54 | - (void)mouseUp:(NSEvent *)theEvent{
55 | float x = self.startPoint.x < self.endPoint.x ? self.startPoint.x : self.endPoint.x;
56 | float y = self.startPoint.y < self.endPoint.y ? self.startPoint.y : self.endPoint.y;
57 | float width = fabs(-self.startPoint.x + self.endPoint.x);
58 | float height = fabs(-self.startPoint.y + self.endPoint.y);
59 |
60 | [self.shapeLayer removeFromSuperlayer];
61 | self.shapeLayer = nil;
62 | [self.window setMovable:YES];
63 | [self removeFromSuperview];
64 | [[NSCursor arrowCursor] set];
65 |
66 | if(width * height >= 400) [self.delegate onSelcetion:NSMakeRect(x, y, width, height)];
67 | }
68 |
69 | @end
70 |
71 |
--------------------------------------------------------------------------------
/pip/window.h:
--------------------------------------------------------------------------------
1 | //
2 | // Window.h
3 | // pip
4 | //
5 | // Created by Amit Verma on 05/12/17.
6 | // Copyright © 2017 boggyb. All rights reserved.
7 | //
8 |
9 | #ifndef Window_h
10 | #define Window_h
11 |
12 | #import "pip.h"
13 | #import "receiver.h"
14 | #import "imageView.h"
15 | #import "preferences.h"
16 | #import "selectionView.h"
17 |
18 | @class VButton;
19 |
20 | @protocol ButtonDelegate
21 | - (void) onClick:(VButton*)button;
22 | @end
23 |
24 | @protocol RootViewDelegate
25 | - (void)onDoubleClick:(NSEvent *)theEvent;
26 | - (void)rightMouseDown:(NSEvent *)theEvent;
27 | @end
28 |
29 | @protocol WindowDelegate
30 | - (void)togglePin;
31 | - (void)togglePlayback;
32 | - (void)toggleNativePip;
33 | - (void)setScale:(id)sender;
34 | @end
35 |
36 | @interface RootView : NSVisualEffectView
37 | @property (nonatomic) id delegate;
38 | @end
39 |
40 | @interface VButton : NSVisualEffectView
41 | @property (nonatomic) id delegate;
42 | @property (nonatomic) float imageScale;
43 | - (id) initWithRadius:(int)radius andImage:(NSImage*) img andImageScale:(float)scale;
44 | - (void) setImage:(NSImage*) img;
45 | - (bool) getEnabled;
46 | - (void) setEnable:(bool) en;
47 | @end
48 |
49 | @interface Window : NSPanel
50 | @property (nonatomic) void* conn;
51 | - (id) initWithAirplay:(bool)enable andTitle:(NSString*)title;
52 | - (void) renderH264:(uint8_t*) data withLength:(size_t) length;
53 | - (void) renderAudio:(uint8_t*) data withLength:(size_t) length;
54 | - (void) setVolume:(float)volume;
55 | - (void) setAudioInputFormat:(UInt32)format withsampleRate:(UInt32)sampleRate andChannels:(UInt32)channelCount andSPF:(UInt32)spf;
56 | @end
57 | #endif /* Window_h */
58 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | # set -x
2 |
3 | SRC_ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4 |
5 | cd $SRC_ROOT_DIR
6 |
7 | PROJECT_PATH="$SRC_ROOT_DIR"
8 |
9 | BUILD_PATH="$SRC_ROOT_DIR/.build"
10 | [[ ! -z "${getDevBuildPath}" ]] && eval "$getDevBuildPath" && BUILD_PATH=$(getDevBuildPath);
11 |
12 | NUM_CPU=$(getconf _NPROCESSORS_ONLN)
13 | # NUM_CPU=1
14 |
15 | type "cmake" > /dev/null 2>&1;
16 | cmake_available=$?
17 | set -e
18 |
19 |
20 | if [[ "$cmake_available" == "0" ]]; then
21 | MAKE_ARGS="-s"
22 | # VERBOSE_ARGS="-DCMAKE_VERBOSE_MAKEFILE=TRUE"
23 | fi
24 |
25 | if [[ $1 == "-v" ]]; then
26 | shift;
27 | if [[ "$cmake_available" == "0" ]]; then
28 | MAKE_ARGS=""
29 | else
30 | MAKE_ARGS="-v"
31 | fi
32 | fi
33 |
34 | run_inline(){
35 | echo "cmake not found, building inline without airplay"
36 | mkdir -p $BUILD_PATH
37 | APP=$BUILD_PATH/$1
38 | clang $MAKE_ARGS -DNO_AIRPLAY -Wl,-dead_strip pip/*.m -o $APP -fobjc-arc -fobjc-link-runtime -O3 -g0 -Wno-deprecated-declarations -F /System/Library/PrivateFrameworks \
39 | -framework Cocoa -framework VideoToolbox -framework AudioToolbox -framework CoreMedia -framework QuartzCore -framework OpenGL -framework Metal -framework MetalKit -framework PIP -framework SkyLight
40 | printSize $1;
41 | $APP $@
42 | }
43 |
44 | run(){
45 | cd $BUILD_PATH
46 | ./$@
47 | cd ~-
48 | }
49 |
50 | build(){
51 | mkdir -p $BUILD_PATH
52 | cd $BUILD_PATH
53 | [[ ! -f "Makefile" ]] && cmake $VERBOSE_ARGS $PROJECT_PATH
54 | make $MAKE_ARGS -j $NUM_CPU $@
55 | cd ~-
56 | }
57 |
58 | printSize(){
59 | echo BUILD_PATH: $BUILD_PATH
60 | cd $BUILD_PATH
61 |
62 | exec_files_array=(${@})
63 | if [ -z "$exec_files_array" ]; then
64 | executables=$(find . -maxdepth 1 -executable -type f -printf '%f ' || find . -maxdepth 1 -perm +0111 -type f)
65 | if [ ! -z "$executables" ]; then
66 | echo $executables | xargs md5
67 | echo $executables | xargs size
68 | echo $executables | xargs ls -la
69 | fi
70 | return
71 | fi
72 |
73 | for exec in "${exec_files_array[@]}"
74 | do
75 | md5 $exec
76 | size $exec
77 | ls -la $exec
78 | done
79 | cd ~-
80 | }
81 |
82 | compile(){
83 | build $@;
84 | printSize $@;
85 | }
86 |
87 | if [[ "$cmake_available" == "0" ]]; then
88 | compile pip;
89 | run pip $@;
90 | else
91 | run_inline PiP $@
92 | fi
93 |
--------------------------------------------------------------------------------
/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from __future__ import unicode_literals
3 |
4 | import biplist
5 | import os.path
6 |
7 | #
8 | # Example settings file for dmgbuild
9 | #
10 |
11 | # Use like this: dmgbuild -s settings.py "Test Volume" test.dmg
12 |
13 | # You can actually use this file for your own application (not just TextEdit)
14 | # by doing e.g.
15 | #
16 | # dmgbuild -s settings.py -D app=/path/to/My.app "My Application" MyApp.dmg
17 |
18 | # .. Useful stuff ..............................................................
19 |
20 | application = defines.get('app', 'build/Release/PiP.app')
21 | appname = os.path.basename(application)
22 |
23 | def icon_from_app(app_path):
24 | plist_path = os.path.join(app_path, 'Contents', 'Info.plist')
25 | plist = biplist.readPlist(plist_path)
26 | icon_name = plist['CFBundleIconFile']
27 | icon_root,icon_ext = os.path.splitext(icon_name)
28 | if not icon_ext:
29 | icon_ext = '.icns'
30 | icon_name = icon_root + icon_ext
31 | return os.path.join(app_path, 'Contents', 'Resources', icon_name)
32 |
33 | # .. Basics ....................................................................
34 |
35 | # Uncomment to override the output filename
36 | # filename = 'test.dmg'
37 |
38 | # Uncomment to override the output volume name
39 | # volume_name = 'Test'
40 |
41 | # Volume format (see hdiutil create -help)
42 | format = defines.get('format', 'UDBZ')
43 |
44 | # Compression level (if relevant)
45 | # compression_level = 9
46 |
47 | # Volume size
48 | size = defines.get('size', None)
49 |
50 | # Files to include
51 | files = [ application ]
52 |
53 | # Symlinks to create
54 | symlinks = { 'Applications': '/Applications' }
55 |
56 | # Volume icon
57 | #
58 | # You can either define icon, in which case that icon file will be copied to the
59 | # image, *or* you can define badge_icon, in which case the icon file you specify
60 | # will be used to badge the system's Removable Disk icon. Badge icons require
61 | # pyobjc-framework-Quartz.
62 | #
63 | #icon = '/path/to/icon.icns'
64 | # badge_icon = icon_from_app(application)
65 |
66 | # Where to put the icons
67 | icon_locations = {
68 | appname: (140, 120),
69 | 'Applications': (500, 120)
70 | }
71 |
72 | # .. Window configuration ......................................................
73 |
74 | # Background
75 | #
76 | # This is a STRING containing any of the following:
77 | #
78 | # #3344ff - web-style RGB color
79 | # #34f - web-style RGB color, short form (#34f == #3344ff)
80 | # rgb(1,0,0) - RGB color, each value is between 0 and 1
81 | # hsl(120,1,.5) - HSL (hue saturation lightness) color
82 | # hwb(300,0,0) - HWB (hue whiteness blackness) color
83 | # cmyk(0,1,0,0) - CMYK color
84 | # goldenrod - X11/SVG named color
85 | # builtin-arrow - A simple built-in background with a blue arrow
86 | # /foo/bar/baz.png - The path to an image file
87 | #
88 | # The hue component in hsl() and hwb() may include a unit; it defaults to
89 | # degrees ('deg'), but also supports radians ('rad') and gradians ('grad'
90 | # or 'gon').
91 | #
92 | # Other color components may be expressed either in the range 0 to 1, or
93 | # as percentages (e.g. 60% is equivalent to 0.6).
94 | background = 'builtin-arrow'
95 |
96 | show_status_bar = False
97 | show_tab_view = False
98 | show_toolbar = False
99 | show_pathbar = False
100 | show_sidebar = False
101 | sidebar_width = 180
102 |
103 | # Window position in ((x, y), (w, h)) format
104 | window_rect = ((100, 100), (640, 360))
105 |
106 | # Select the default view; must be one of
107 | #
108 | # 'icon-view'
109 | # 'list-view'
110 | # 'column-view'
111 | # 'coverflow'
112 | #
113 | default_view = 'icon-view'
114 |
115 | # General view configuration
116 | show_icon_preview = True
117 |
118 | # Set these to True to force inclusion of icon/list view settings (otherwise
119 | # we only include settings for the default view)
120 | include_icon_view_settings = 'auto'
121 | include_list_view_settings = 'auto'
122 |
123 | # .. Icon view configuration ...................................................
124 |
125 | arrange_by = None
126 | grid_offset = (0, 0)
127 | grid_spacing = 100
128 | scroll_position = (0, 0)
129 | label_pos = 'bottom' # or 'right'
130 | text_size = 16
131 | icon_size = 128
132 |
--------------------------------------------------------------------------------