├── .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 | Total Downloads 4 | App Version 5 | Repo Size 6 | Repo Stars 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 | Latest Release Latest Release 34 | 35 | ### Download and install via Homebrew 36 | Homebrew 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 | --------------------------------------------------------------------------------