From 740e78cb2a00fde3e12fa8f7b8f3961752e81a82 Mon Sep 17 00:00:00 2001 From: fduncanh Date: Tue, 10 Aug 2021 01:45:01 -0400 Subject: [PATCH] reverse accidental overwrite of raop.h by raop.c in previous commit --- lib/raop.h | 484 +++++++---------------------------------------------- 1 file changed, 60 insertions(+), 424 deletions(-) diff --git a/lib/raop.h b/lib/raop.h index cd7ca82..bd02d17 100755 --- a/lib/raop.h +++ b/lib/raop.h @@ -1,437 +1,73 @@ -/** - * Copyright (C) 2011-2012 Juho Vähä-Herttua - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - */ +#ifndef RAOP_H +#define RAOP_H -#include -#include -#include -#include - -#include "raop.h" -#include "raop_rtp.h" -#include "raop_rtp.h" -#include "pairing.h" -#include "httpd.h" - -#include "global.h" -#include "fairplay.h" -#include "netutils.h" -#include "logger.h" -#include "compat.h" -#include "raop_rtp_mirror.h" +#include "dnssd.h" +#include "stream.h" #include "raop_ntp.h" -struct raop_s { - /* Callbacks for audio and video */ - raop_callbacks_t callbacks; +#if defined (WIN32) && defined(DLL_EXPORT) +# define RAOP_API __declspec(dllexport) +#else +# define RAOP_API +#endif - /* Logger instance */ - logger_t *logger; +#ifdef __cplusplus +extern "C" { +#endif - /* Pairing, HTTP daemon and RSA key */ - pairing_t *pairing; - httpd_t *httpd; - dnssd_t *dnssd; +/* Define syslog style log levels */ +#define RAOP_LOG_EMERG 0 /* system is unusable */ +#define RAOP_LOG_ALERT 1 /* action must be taken immediately */ +#define RAOP_LOG_CRIT 2 /* critical conditions */ +#define RAOP_LOG_ERR 3 /* error conditions */ +#define RAOP_LOG_WARNING 4 /* warning conditions */ +#define RAOP_LOG_NOTICE 5 /* normal but significant condition */ +#define RAOP_LOG_INFO 6 /* informational */ +#define RAOP_LOG_DEBUG 7 /* debug-level messages */ - unsigned short port; - unsigned short timing_lport; - unsigned short control_lport; - unsigned short data_lport; - unsigned short mirror_data_lport; - unsigned short display_width; - unsigned short display_height; - unsigned short display_refresh_rate; - unsigned short display_max_fps; +typedef struct raop_s raop_t; + +typedef void (*raop_log_callback_t)(void *cls, int level, const char *msg); + +struct raop_callbacks_s { + void* cls; + + void (*audio_process)(void *cls, raop_ntp_t *ntp, aac_decode_struct *data); + void (*video_process)(void *cls, raop_ntp_t *ntp, h264_decode_struct *data); + + /* Optional but recommended callback functions */ + void (*conn_init)(void *cls); + void (*conn_destroy)(void *cls); + void (*audio_flush)(void *cls); + void (*video_flush)(void *cls); + void (*audio_set_volume)(void *cls, float volume); + void (*audio_set_metadata)(void *cls, const void *buffer, int buflen); + void (*audio_set_coverart)(void *cls, const void *buffer, int buflen); + void (*audio_remote_control_id)(void *cls, const char *dacp_id, const char *active_remote_header); + void (*audio_set_progress)(void *cls, unsigned int start, unsigned int curr, unsigned int end); }; +typedef struct raop_callbacks_s raop_callbacks_t; -struct raop_conn_s { - raop_t *raop; - raop_ntp_t *raop_ntp; - raop_rtp_t *raop_rtp; - raop_rtp_mirror_t *raop_rtp_mirror; - fairplay_t *fairplay; - pairing_session_t *pairing; +RAOP_API raop_t *raop_init(int max_clients, raop_callbacks_t *callbacks); - unsigned char *local; - int locallen; +RAOP_API void raop_set_log_level(raop_t *raop, int level); +RAOP_API void raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls); +RAOP_API void raop_set_display(raop_t *raop, unsigned short width, unsigned short height, + unsigned short refresh_rate, unsigned short max_fps); +RAOP_API void raop_set_port(raop_t *raop, unsigned short port); +RAOP_API void raop_set_udp_ports(raop_t *raop, unsigned short port[3]); +RAOP_API void raop_set_tcp_ports(raop_t *raop, unsigned short port[2]); +RAOP_API unsigned short raop_get_port(raop_t *raop); +RAOP_API void *raop_get_callback_cls(raop_t *raop); +RAOP_API int raop_start(raop_t *raop, unsigned short *port); +RAOP_API int raop_is_running(raop_t *raop); +RAOP_API void raop_stop(raop_t *raop); +RAOP_API void raop_set_dnssd(raop_t *raop, dnssd_t *dnssd); +RAOP_API void raop_destroy(raop_t *raop); - unsigned char *remote; - int remotelen; - -}; -typedef struct raop_conn_s raop_conn_t; - -#include "raop_handlers.h" - -static void * -conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remote, int remotelen) { - raop_t *raop = opaque; - raop_conn_t *conn; - - assert(raop); - - conn = calloc(1, sizeof(raop_conn_t)); - if (!conn) { - return NULL; - } - conn->raop = raop; - conn->raop_rtp = NULL; - conn->raop_ntp = NULL; - conn->fairplay = fairplay_init(raop->logger); - - if (!conn->fairplay) { - free(conn); - return NULL; - } - conn->pairing = pairing_session_init(raop->pairing); - if (!conn->pairing) { - fairplay_destroy(conn->fairplay); - free(conn); - return NULL; - } - - if (locallen == 4) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Local: %d.%d.%d.%d", - local[0], local[1], local[2], local[3]); - } else if (locallen == 16) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Local: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - local[0], local[1], local[2], local[3], local[4], local[5], local[6], local[7], - local[8], local[9], local[10], local[11], local[12], local[13], local[14], local[15]); - } - if (remotelen == 4) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Remote: %d.%d.%d.%d", - remote[0], remote[1], remote[2], remote[3]); - } else if (remotelen == 16) { - logger_log(conn->raop->logger, LOGGER_INFO, - "Remote: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", - remote[0], remote[1], remote[2], remote[3], remote[4], remote[5], remote[6], remote[7], - remote[8], remote[9], remote[10], remote[11], remote[12], remote[13], remote[14], remote[15]); - } - - conn->local = malloc(locallen); - assert(conn->local); - memcpy(conn->local, local, locallen); - - conn->remote = malloc(remotelen); - assert(conn->remote); - memcpy(conn->remote, remote, remotelen); - - conn->locallen = locallen; - conn->remotelen = remotelen; - - if (raop->callbacks.conn_init) { - raop->callbacks.conn_init(raop->callbacks.cls); - } - - return conn; -} - -static void -conn_request(void *ptr, http_request_t *request, http_response_t **response) { - raop_conn_t *conn = ptr; - logger_log(conn->raop->logger, LOGGER_DEBUG, "conn_request"); - const char *method; - const char *url; - const char *cseq; - - char *response_data = NULL; - int response_datalen = 0; - - method = http_request_get_method(request); - url = http_request_get_url(request); - cseq = http_request_get_header(request, "CSeq"); - if (!method || !cseq) { - return; - } - - *response = http_response_init("RTSP/1.0", 200, "OK"); - - http_response_add_header(*response, "CSeq", cseq); - //http_response_add_header(*response, "Apple-Jack-Status", "connected; type=analog"); - http_response_add_header(*response, "Server", "AirTunes/220.68"); - - logger_log(conn->raop->logger, LOGGER_DEBUG, "Handling request %s with URL %s", method, url); - raop_handler_t handler = NULL; - if (!strcmp(method, "GET") && !strcmp(url, "/info")) { - handler = &raop_handler_info; - } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-setup")) { - handler = &raop_handler_pairsetup; - } else if (!strcmp(method, "POST") && !strcmp(url, "/pair-verify")) { - handler = &raop_handler_pairverify; - } else if (!strcmp(method, "POST") && !strcmp(url, "/fp-setup")) { - handler = &raop_handler_fpsetup; - } else if (!strcmp(method, "OPTIONS")) { - handler = &raop_handler_options; - } else if (!strcmp(method, "SETUP")) { - handler = &raop_handler_setup; - } else if (!strcmp(method, "GET_PARAMETER")) { - handler = &raop_handler_get_parameter; - } else if (!strcmp(method, "SET_PARAMETER")) { - handler = &raop_handler_set_parameter; - } else if (!strcmp(method, "POST") && !strcmp(url, "/feedback")) { - handler = &raop_handler_feedback; - } else if (!strcmp(method, "RECORD")) { - handler = &raop_handler_record; - } else if (!strcmp(method, "FLUSH")) { - const char *rtpinfo; - int next_seq = -1; - - rtpinfo = http_request_get_header(request, "RTP-Info"); - if (rtpinfo) { - logger_log(conn->raop->logger, LOGGER_DEBUG, "Flush with RTP-Info: %s", rtpinfo); - if (!strncmp(rtpinfo, "seq=", 4)) { - next_seq = strtol(rtpinfo + 4, NULL, 10); - } - } - if (conn->raop_rtp) { - raop_rtp_flush(conn->raop_rtp, next_seq); - } else { - logger_log(conn->raop->logger, LOGGER_WARNING, "RAOP not initialized at FLUSH"); - } - } else if (!strcmp(method, "TEARDOWN")) { - //http_response_add_header(*response, "Connection", "close"); - if (conn->raop_rtp != NULL && raop_rtp_is_running(conn->raop_rtp)) { - /* Destroy our RTP session */ - raop_rtp_stop(conn->raop_rtp); - } else if (conn->raop_rtp_mirror) { - /* Destroy our sessions */ - raop_rtp_destroy(conn->raop_rtp); - conn->raop_rtp = NULL; - raop_rtp_mirror_destroy(conn->raop_rtp_mirror); - conn->raop_rtp_mirror = NULL; - } - } - if (handler != NULL) { - handler(conn, request, *response, &response_data, &response_datalen); - } - http_response_finish(*response, response_data, response_datalen); - if (response_data) { - free(response_data); - response_data = NULL; - response_datalen = 0; - } -} - -static void -conn_destroy(void *ptr) { - raop_conn_t *conn = ptr; - - logger_log(conn->raop->logger, LOGGER_INFO, "Destroying connection"); - - if (conn->raop->callbacks.conn_destroy) { - conn->raop->callbacks.conn_destroy(conn->raop->callbacks.cls); - } - - if (conn->raop_ntp) { - raop_ntp_destroy(conn->raop_ntp); - } - if (conn->raop_rtp) { - /* This is done in case TEARDOWN was not called */ - raop_rtp_destroy(conn->raop_rtp); - } - if (conn->raop_rtp_mirror) { - /* This is done in case TEARDOWN was not called */ - raop_rtp_mirror_destroy(conn->raop_rtp_mirror); - } - - conn->raop->callbacks.video_flush(conn->raop->callbacks.cls); - - free(conn->local); - free(conn->remote); - pairing_session_destroy(conn->pairing); - fairplay_destroy(conn->fairplay); - free(conn); -} - -raop_t * -raop_init(int max_clients, raop_callbacks_t *callbacks) { - raop_t *raop; - pairing_t *pairing; - httpd_t *httpd; - httpd_callbacks_t httpd_cbs; - - assert(callbacks); - assert(max_clients > 0); - assert(max_clients < 100); - - /* Initialize the network */ - if (netutils_init() < 0) { - return NULL; - } - - /* Validate the callbacks structure */ - if (!callbacks->audio_process || - !callbacks->video_process) { - return NULL; - } - - /* Allocate the raop_t structure */ - raop = calloc(1, sizeof(raop_t)); - if (!raop) { - return NULL; - } - - /* Initialize the logger */ - raop->logger = logger_init(); - pairing = pairing_init_generate(); - if (!pairing) { - free(raop); - return NULL; - } - - /* Set HTTP callbacks to our handlers */ - memset(&httpd_cbs, 0, sizeof(httpd_cbs)); - httpd_cbs.opaque = raop; - httpd_cbs.conn_init = &conn_init; - httpd_cbs.conn_request = &conn_request; - httpd_cbs.conn_destroy = &conn_destroy; - - /* Initialize the http daemon */ - httpd = httpd_init(raop->logger, &httpd_cbs, max_clients); - if (!httpd) { - pairing_destroy(pairing); - free(raop); - return NULL; - } - /* Copy callbacks structure */ - memcpy(&raop->callbacks, callbacks, sizeof(raop_callbacks_t)); - raop->pairing = pairing; - raop->httpd = httpd; - - /* initialize network port list */ - raop->port = 0; - raop->timing_lport = 0; - raop->control_lport = 0; - raop->data_lport = 0; - raop->mirror_data_lport = 0; - - /* initialize display width, height, refresh_rate, max_fps */ - raop->display_width = 1920; - raop->display_height = 1080; - raop->display_refresh_rate = 60; - raop->display_max_fps = 30; - - return raop; -} - -void -raop_destroy(raop_t *raop) { - if (raop) { - raop_stop(raop); - pairing_destroy(raop->pairing); - httpd_destroy(raop->httpd); - logger_destroy(raop->logger); - free(raop); - - /* Cleanup the network */ - netutils_cleanup(); - } -} - -int -raop_is_running(raop_t *raop) { - assert(raop); - - return httpd_is_running(raop->httpd); -} - -void -raop_set_log_level(raop_t *raop, int level) { - assert(raop); - - logger_set_level(raop->logger, level); -} - -void raop_set_display(raop_t *raop, unsigned short width, unsigned short height, - unsigned short refresh_rate, unsigned short max_fps){ - assert(raop); - - if (width) raop->display_width = width; - if (height) raop->display_height = height; - - // these must fit into a single byte - if (refresh_rate > 255) refresh_rate = 255; - if (max_fps > 255) max_fps = 255; - - if (refresh_rate) raop->display_refresh_rate = refresh_rate; - if (max_fps) raop->display_max_fps = max_fps; - - if (raop->display_max_fps > raop->display_refresh_rate) { - raop->display_max_fps = raop->display_refresh_rate; - } -} - -void -raop_set_port(raop_t *raop, unsigned short port) { - assert(raop); - raop->port = port; -} - -void -raop_set_udp_ports(raop_t *raop, unsigned short udp[3]) { - assert(raop); - raop->timing_lport = udp[0]; - raop->control_lport = udp[1]; - raop->data_lport = udp[2]; -} - -void -raop_set_tcp_ports(raop_t *raop, unsigned short tcp[2]) { - assert(raop); - raop->mirror_data_lport = tcp[0]; - raop->port = tcp[1]; -} - -unsigned short -raop_get_port(raop_t *raop) { - assert(raop); - return raop->port; -} - -void * -raop_get_callback_cls(raop_t *raop) { - assert(raop); - return raop->callbacks.cls; -} - -void -raop_set_log_callback(raop_t *raop, raop_log_callback_t callback, void *cls) { - assert(raop); - - logger_set_callback(raop->logger, callback, cls); -} - -void -raop_set_dnssd(raop_t *raop, dnssd_t *dnssd) { - assert(dnssd); - raop->dnssd = dnssd; -} - - -int -raop_start(raop_t *raop, unsigned short *port) { - assert(raop); - assert(port); - return httpd_start(raop->httpd, port); -} - -void -raop_stop(raop_t *raop) { - assert(raop); - httpd_stop(raop->httpd); +#ifdef __cplusplus } +#endif +#endif