mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
rework airplay_video to store multiple playlists
This commit is contained in:
@@ -52,21 +52,17 @@ struct airplay_video_s {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// initialize airplay_video service.
|
// initialize airplay_video service.
|
||||||
int airplay_video_service_init(raop_t *raop, unsigned short http_port,
|
airplay_video_t *airplay_video_service_init(raop_t *raop, unsigned short http_port,
|
||||||
const char *lang, const char *session_id) {
|
const char *lang, const char *session_id) {
|
||||||
char uri[] = "http://localhost:xxxxx";
|
char uri[] = "http://localhost:xxxxx";
|
||||||
assert(raop);
|
assert(raop);
|
||||||
|
|
||||||
airplay_video_t *airplay_video = deregister_airplay_video(raop);
|
|
||||||
if (airplay_video) {
|
|
||||||
airplay_video_service_destroy(airplay_video);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* calloc guarantees that the 36-character strings apple_session_id and
|
/* calloc guarantees that the 36-character strings apple_session_id and
|
||||||
playback_uuid are null-terminated */
|
playback_uuid are null-terminated */
|
||||||
airplay_video = (airplay_video_t *) calloc(1, sizeof(airplay_video_t));
|
airplay_video_t *airplay_video = (airplay_video_t *) calloc(1, sizeof(airplay_video_t));
|
||||||
|
|
||||||
if (!airplay_video) {
|
if (!airplay_video) {
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
airplay_video->lang = lang;
|
airplay_video->lang = lang;
|
||||||
@@ -79,10 +75,6 @@ int airplay_video_service_init(raop_t *raop, unsigned short http_port,
|
|||||||
*ptr = '\0';
|
*ptr = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!register_airplay_video(raop, airplay_video)) {
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf(" %p %p\n", airplay_video, get_airplay_video(raop));
|
//printf(" %p %p\n", airplay_video, get_airplay_video(raop));
|
||||||
|
|
||||||
airplay_video->raop = raop;
|
airplay_video->raop = raop;
|
||||||
@@ -99,7 +91,7 @@ int airplay_video_service_init(raop_t *raop, unsigned short http_port,
|
|||||||
airplay_video->master_playlist = NULL;
|
airplay_video->master_playlist = NULL;
|
||||||
airplay_video->num_uri = 0;
|
airplay_video->num_uri = 0;
|
||||||
airplay_video->next_uri = 0;
|
airplay_video->next_uri = 0;
|
||||||
return 0;
|
return airplay_video;
|
||||||
}
|
}
|
||||||
|
|
||||||
// destroy the airplay_video service
|
// destroy the airplay_video service
|
||||||
|
|||||||
@@ -84,8 +84,28 @@ http_handler_server_info(raop_conn_t *conn, http_request_t *request, http_respon
|
|||||||
/* initialize the airplay video service */
|
/* initialize the airplay video service */
|
||||||
const char *session_id = http_request_get_header(request, "X-Apple-Session-ID");
|
const char *session_id = http_request_get_header(request, "X-Apple-Session-ID");
|
||||||
|
|
||||||
airplay_video_service_init(conn->raop, conn->raop->port, conn->raop->lang, session_id);
|
int id = -1;
|
||||||
|
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
|
||||||
|
if (conn->raop->airplay_video[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
id = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (id == -1) {
|
||||||
|
logger_log(conn->raop->logger, LOGGER_ERR, "no unused airplay_video structures are available"
|
||||||
|
" MAX_AIRPLAY_VIDEO = %d\n", MAX_AIRPLAY_VIDEO);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
airplay_video_t *airplay_video = airplay_video_service_init(conn->raop, conn->raop->port, conn->raop->lang, session_id);
|
||||||
|
if (airplay_video) {
|
||||||
|
conn->raop->current_video = id;
|
||||||
|
conn->raop->airplay_video[id] = airplay_video;
|
||||||
|
} else {
|
||||||
|
logger_log(conn->raop->logger, LOGGER_ERR, "failed to allocate airplay_video[%d]\n", id);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -123,7 +143,7 @@ http_handler_rate(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
float value = strtof(rate, &end);
|
float value = strtof(rate, &end);
|
||||||
if (end && end != rate) {
|
if (end && end != rate) {
|
||||||
rate_value = value;
|
rate_value = value;
|
||||||
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_rate: got rate = %.6f", rate_value);
|
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_rate: got rate = %.6f", rate_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn->raop->callbacks.on_video_rate(conn->raop->callbacks.cls, rate_value);
|
conn->raop->callbacks.on_video_rate(conn->raop->callbacks.cls, rate_value);
|
||||||
@@ -360,6 +380,7 @@ static void
|
|||||||
http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
||||||
char **response_data, int *response_datalen) {
|
char **response_data, int *response_datalen) {
|
||||||
|
|
||||||
|
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
|
||||||
bool data_is_plist = false;
|
bool data_is_plist = false;
|
||||||
plist_t req_root_node = NULL;
|
plist_t req_root_node = NULL;
|
||||||
uint64_t uint_val;
|
uint64_t uint_val;
|
||||||
@@ -372,7 +393,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
|
|||||||
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
|
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
|
||||||
goto post_action_error;
|
goto post_action_error;
|
||||||
}
|
}
|
||||||
const char *apple_session_id = get_apple_session_id(conn->raop->airplay_video);
|
const char *apple_session_id = get_apple_session_id(airplay_video);
|
||||||
if (strcmp(session_id, apple_session_id)){
|
if (strcmp(session_id, apple_session_id)){
|
||||||
logger_log(conn->raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
|
logger_log(conn->raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
|
||||||
apple_session_id, session_id);
|
apple_session_id, session_id);
|
||||||
@@ -433,7 +454,7 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
|
|||||||
plist_t req_params_item_uuid_node = plist_dict_get_item(req_params_item_node, "uuid");
|
plist_t req_params_item_uuid_node = plist_dict_get_item(req_params_item_node, "uuid");
|
||||||
char* remove_uuid = NULL;
|
char* remove_uuid = NULL;
|
||||||
plist_get_string_val(req_params_item_uuid_node, &remove_uuid);
|
plist_get_string_val(req_params_item_uuid_node, &remove_uuid);
|
||||||
const char *playback_uuid = get_playback_uuid(conn->raop->airplay_video);
|
const char *playback_uuid = get_playback_uuid(airplay_video);
|
||||||
if (strcmp(remove_uuid, playback_uuid)) {
|
if (strcmp(remove_uuid, playback_uuid)) {
|
||||||
logger_log(conn->raop->logger, LOGGER_ERR, "uuid of playlist removal action request did not match current playlist:\n"
|
logger_log(conn->raop->logger, LOGGER_ERR, "uuid of playlist removal action request did not match current playlist:\n"
|
||||||
" current: %s\n remove: %s", playback_uuid, remove_uuid);
|
" current: %s\n remove: %s", playback_uuid, remove_uuid);
|
||||||
@@ -557,25 +578,25 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
|
|||||||
char *ptr = strstr(fcup_response_url, "/master.m3u8");
|
char *ptr = strstr(fcup_response_url, "/master.m3u8");
|
||||||
if (ptr) {
|
if (ptr) {
|
||||||
/* this is a master playlist */
|
/* this is a master playlist */
|
||||||
char *uri_prefix = get_uri_prefix(conn->raop->airplay_video);
|
char *uri_prefix = get_uri_prefix(airplay_video);
|
||||||
char ** media_data_store = NULL;
|
char ** media_data_store = NULL;
|
||||||
int num_uri = 0;
|
int num_uri = 0;
|
||||||
|
|
||||||
char *uri_local_prefix = get_uri_local_prefix(conn->raop->airplay_video);
|
char *uri_local_prefix = get_uri_local_prefix(airplay_video);
|
||||||
char *new_master = adjust_master_playlist (fcup_response_data, fcup_response_datalen, uri_prefix, uri_local_prefix);
|
char *new_master = adjust_master_playlist (fcup_response_data, fcup_response_datalen, uri_prefix, uri_local_prefix);
|
||||||
store_master_playlist(conn->raop->airplay_video, new_master);
|
store_master_playlist(airplay_video, new_master);
|
||||||
create_media_uri_table(uri_prefix, fcup_response_data, fcup_response_datalen, &media_data_store, &num_uri);
|
create_media_uri_table(uri_prefix, fcup_response_data, fcup_response_datalen, &media_data_store, &num_uri);
|
||||||
create_media_data_store(conn->raop->airplay_video, media_data_store, num_uri);
|
create_media_data_store(airplay_video, media_data_store, num_uri);
|
||||||
num_uri = get_num_media_uri(conn->raop->airplay_video);
|
num_uri = get_num_media_uri(airplay_video);
|
||||||
set_next_media_uri_id(conn->raop->airplay_video, 0);
|
set_next_media_uri_id(airplay_video, 0);
|
||||||
} else {
|
} else {
|
||||||
/* this is a media playlist */
|
/* this is a media playlist */
|
||||||
assert(fcup_response_data);
|
assert(fcup_response_data);
|
||||||
char *playlist = (char *) calloc(fcup_response_datalen + 1, sizeof(char));
|
char *playlist = (char *) calloc(fcup_response_datalen + 1, sizeof(char));
|
||||||
memcpy(playlist, fcup_response_data, fcup_response_datalen);
|
memcpy(playlist, fcup_response_data, fcup_response_datalen);
|
||||||
int uri_num = get_next_media_uri_id(conn->raop->airplay_video);
|
int uri_num = get_next_media_uri_id(airplay_video);
|
||||||
--uri_num; // (next num is current num + 1)
|
--uri_num; // (next num is current num + 1)
|
||||||
store_media_playlist(conn->raop->airplay_video, playlist, uri_num);
|
store_media_playlist(airplay_video, playlist, uri_num);
|
||||||
float duration = 0.0f;
|
float duration = 0.0f;
|
||||||
int count = analyze_media_playlist(playlist, &duration);
|
int count = analyze_media_playlist(playlist, &duration);
|
||||||
if (count) {
|
if (count) {
|
||||||
@@ -590,18 +611,18 @@ http_handler_action(raop_conn_t *conn, http_request_t *request, http_response_t
|
|||||||
}
|
}
|
||||||
plist_mem_free(fcup_response_url);
|
plist_mem_free(fcup_response_url);
|
||||||
|
|
||||||
int num_uri = get_num_media_uri(conn->raop->airplay_video);
|
int num_uri = get_num_media_uri(airplay_video);
|
||||||
int uri_num = get_next_media_uri_id(conn->raop->airplay_video);
|
int uri_num = get_next_media_uri_id(airplay_video);
|
||||||
if (uri_num < num_uri) {
|
if (uri_num < num_uri) {
|
||||||
fcup_request((void *) conn, get_media_uri_by_num(conn->raop->airplay_video, uri_num),
|
fcup_request((void *) conn, get_media_uri_by_num(airplay_video, uri_num),
|
||||||
apple_session_id,
|
apple_session_id,
|
||||||
get_next_FCUP_RequestID(conn->raop->airplay_video));
|
get_next_FCUP_RequestID(airplay_video));
|
||||||
set_next_media_uri_id(conn->raop->airplay_video, ++uri_num);
|
set_next_media_uri_id(airplay_video, ++uri_num);
|
||||||
} else {
|
} else {
|
||||||
char * uri_local_prefix = get_uri_local_prefix(conn->raop->airplay_video);
|
char * uri_local_prefix = get_uri_local_prefix(airplay_video);
|
||||||
conn->raop->callbacks.on_video_play(conn->raop->callbacks.cls,
|
conn->raop->callbacks.on_video_play(conn->raop->callbacks.cls,
|
||||||
strcat(uri_local_prefix, "/master.m3u8"),
|
strcat(uri_local_prefix, "/master.m3u8"),
|
||||||
get_start_position_seconds(conn->raop->airplay_video));
|
get_start_position_seconds(airplay_video));
|
||||||
}
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
@@ -626,6 +647,7 @@ static void
|
|||||||
http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
||||||
char **response_data, int *response_datalen) {
|
char **response_data, int *response_datalen) {
|
||||||
|
|
||||||
|
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
|
||||||
char* playback_location = NULL;
|
char* playback_location = NULL;
|
||||||
char* client_proc_name = NULL;
|
char* client_proc_name = NULL;
|
||||||
plist_t req_root_node = NULL;
|
plist_t req_root_node = NULL;
|
||||||
@@ -642,7 +664,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
|
logger_log(conn->raop->logger, LOGGER_ERR, "Play request had no X-Apple-Session-ID");
|
||||||
goto play_error;
|
goto play_error;
|
||||||
}
|
}
|
||||||
const char *apple_session_id = get_apple_session_id(conn->raop->airplay_video);
|
const char *apple_session_id = get_apple_session_id(airplay_video);
|
||||||
if (strcmp(session_id, apple_session_id)){
|
if (strcmp(session_id, apple_session_id)){
|
||||||
logger_log(conn->raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
|
logger_log(conn->raop->logger, LOGGER_ERR, "X-Apple-Session-ID has changed:\n was:\"%s\"\n now:\"%s\"",
|
||||||
apple_session_id, session_id);
|
apple_session_id, session_id);
|
||||||
@@ -684,7 +706,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
} else {
|
} else {
|
||||||
char* playback_uuid = NULL;
|
char* playback_uuid = NULL;
|
||||||
plist_get_string_val(req_uuid_node, &playback_uuid);
|
plist_get_string_val(req_uuid_node, &playback_uuid);
|
||||||
set_playback_uuid(conn->raop->airplay_video, playback_uuid);
|
set_playback_uuid(airplay_video, playback_uuid);
|
||||||
plist_mem_free (playback_uuid);
|
plist_mem_free (playback_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,7 +737,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
plist_get_real_val(req_start_position_seconds_node, &start_position);
|
plist_get_real_val(req_start_position_seconds_node, &start_position);
|
||||||
start_position_seconds = (float) start_position;
|
start_position_seconds = (float) start_position;
|
||||||
}
|
}
|
||||||
set_start_position_seconds(conn->raop->airplay_video, (float) start_position_seconds);
|
set_start_position_seconds(airplay_video, (float) start_position_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ptr = strstr(playback_location, "/master.m3u8");
|
char *ptr = strstr(playback_location, "/master.m3u8");
|
||||||
@@ -724,9 +746,9 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
goto play_error;
|
goto play_error;
|
||||||
}
|
}
|
||||||
int prefix_len = (int) (ptr - playback_location);
|
int prefix_len = (int) (ptr - playback_location);
|
||||||
set_uri_prefix(conn->raop->airplay_video, playback_location, prefix_len);
|
set_uri_prefix(airplay_video, playback_location, prefix_len);
|
||||||
set_next_media_uri_id(conn->raop->airplay_video, 0);
|
set_next_media_uri_id(airplay_video, 0);
|
||||||
fcup_request((void *) conn, playback_location, apple_session_id, get_next_FCUP_RequestID(conn->raop->airplay_video));
|
fcup_request((void *) conn, playback_location, apple_session_id, get_next_FCUP_RequestID(airplay_video));
|
||||||
|
|
||||||
plist_mem_free(playback_location);
|
plist_mem_free(playback_location);
|
||||||
|
|
||||||
@@ -757,6 +779,7 @@ http_handler_play(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
static void
|
static void
|
||||||
http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *response,
|
||||||
char **response_data, int *response_datalen) {
|
char **response_data, int *response_datalen) {
|
||||||
|
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
|
||||||
const char *method = http_request_get_method(request);
|
const char *method = http_request_get_method(request);
|
||||||
assert (!strcmp(method, "GET"));
|
assert (!strcmp(method, "GET"));
|
||||||
const char *url = http_request_get_url(request);
|
const char *url = http_request_get_url(request);
|
||||||
@@ -772,7 +795,7 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(url, "/master.m3u8")){
|
if (!strcmp(url, "/master.m3u8")){
|
||||||
char * master_playlist = get_master_playlist(conn->raop->airplay_video);
|
char * master_playlist = get_master_playlist(airplay_video);
|
||||||
if (master_playlist) {
|
if (master_playlist) {
|
||||||
size_t len = strlen(master_playlist);
|
size_t len = strlen(master_playlist);
|
||||||
char * data = (char *) malloc(len + 1);
|
char * data = (char *) malloc(len + 1);
|
||||||
@@ -786,7 +809,7 @@ http_handler_hls(raop_conn_t *conn, http_request_t *request, http_response_t *r
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char *media_playlist = get_media_playlist(conn->raop->airplay_video, url);
|
char *media_playlist = get_media_playlist(airplay_video, url);
|
||||||
if (media_playlist) {
|
if (media_playlist) {
|
||||||
char *data = adjust_yt_condensed_playlist(media_playlist);
|
char *data = adjust_yt_condensed_playlist(media_playlist);
|
||||||
*response_data = data;
|
*response_data = data;
|
||||||
|
|||||||
44
lib/raop.c
44
lib/raop.c
@@ -73,8 +73,10 @@ struct raop_s {
|
|||||||
char pk_str[2*ED25519_KEY_SIZE + 1];
|
char pk_str[2*ED25519_KEY_SIZE + 1];
|
||||||
|
|
||||||
/* place to store media_data_store */
|
/* place to store media_data_store */
|
||||||
airplay_video_t *airplay_video;
|
airplay_video_t *airplay_video[MAX_AIRPLAY_VIDEO];
|
||||||
|
int current_video;
|
||||||
|
int removed_video;
|
||||||
|
|
||||||
/* activate support for HLS live streaming */
|
/* activate support for HLS live streaming */
|
||||||
bool hls_support;
|
bool hls_support;
|
||||||
|
|
||||||
@@ -94,7 +96,6 @@ struct raop_conn_s {
|
|||||||
raop_rtp_mirror_t *raop_rtp_mirror;
|
raop_rtp_mirror_t *raop_rtp_mirror;
|
||||||
fairplay_t *fairplay;
|
fairplay_t *fairplay;
|
||||||
pairing_session_t *session;
|
pairing_session_t *session;
|
||||||
airplay_video_t *airplay_video;
|
|
||||||
|
|
||||||
unsigned char *local;
|
unsigned char *local;
|
||||||
int locallen;
|
int locallen;
|
||||||
@@ -165,7 +166,6 @@ conn_init(void *opaque, unsigned char *local, int locallen, unsigned char *remot
|
|||||||
|
|
||||||
conn->connection_type = CONNECTION_TYPE_UNKNOWN;
|
conn->connection_type = CONNECTION_TYPE_UNKNOWN;
|
||||||
conn->client_session_id = NULL;
|
conn->client_session_id = NULL;
|
||||||
conn->airplay_video = NULL;
|
|
||||||
|
|
||||||
conn->authenticated = false;
|
conn->authenticated = false;
|
||||||
|
|
||||||
@@ -535,9 +535,6 @@ conn_destroy(void *ptr) {
|
|||||||
if (conn->client_session_id) {
|
if (conn->client_session_id) {
|
||||||
free(conn->client_session_id);
|
free(conn->client_session_id);
|
||||||
}
|
}
|
||||||
if (conn->airplay_video) {
|
|
||||||
airplay_video_service_destroy(conn->airplay_video);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(conn);
|
free(conn);
|
||||||
}
|
}
|
||||||
@@ -592,6 +589,13 @@ raop_init(raop_callbacks_t *callbacks) {
|
|||||||
/* initialize switch for display of client's streaming data records */
|
/* initialize switch for display of client's streaming data records */
|
||||||
raop->clientFPSdata = 0;
|
raop->clientFPSdata = 0;
|
||||||
|
|
||||||
|
/* initialize airplay_video */
|
||||||
|
raop->current_video = -1;
|
||||||
|
raop->removed_video = -1;
|
||||||
|
for (int i= 0; i < MAX_AIRPLAY_VIDEO; i++) {
|
||||||
|
raop->airplay_video[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
raop->audio_delay_micros = 250000;
|
raop->audio_delay_micros = 250000;
|
||||||
|
|
||||||
raop->hls_support = false;
|
raop->hls_support = false;
|
||||||
@@ -816,28 +820,12 @@ void raop_remove_hls_connections(raop_t * raop) {
|
|||||||
httpd_remove_connections_by_type(raop->httpd, CONNECTION_TYPE_AIRPLAY);
|
httpd_remove_connections_by_type(raop->httpd, CONNECTION_TYPE_AIRPLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
airplay_video_t *deregister_airplay_video(raop_t *raop) {
|
|
||||||
airplay_video_t *airplay_video = raop->airplay_video;
|
|
||||||
raop->airplay_video = NULL;
|
|
||||||
return airplay_video;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool register_airplay_video(raop_t *raop, airplay_video_t *airplay_video) {
|
|
||||||
if (raop->airplay_video) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
raop->airplay_video = airplay_video;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
airplay_video_t * get_airplay_video(raop_t *raop) {
|
|
||||||
return raop->airplay_video;
|
|
||||||
}
|
|
||||||
|
|
||||||
void raop_destroy_airplay_video(raop_t *raop) {
|
void raop_destroy_airplay_video(raop_t *raop) {
|
||||||
if (raop->airplay_video) {
|
for (int i = 0; i < MAX_AIRPLAY_VIDEO; i++) {
|
||||||
airplay_video_service_destroy(raop->airplay_video);
|
if (raop->airplay_video[i]) {
|
||||||
raop->airplay_video = NULL;
|
airplay_video_service_destroy(raop->airplay_video[i]);
|
||||||
|
raop->airplay_video[i] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
#include "raop_ntp.h"
|
#include "raop_ntp.h"
|
||||||
#include "airplay_video.h"
|
#include "airplay_video.h"
|
||||||
|
|
||||||
# define RAOP_API
|
#define RAOP_API
|
||||||
|
#define MAX_AIRPLAY_VIDEO 2
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -104,11 +105,8 @@ raop_ntp_t *raop_ntp_init(logger_t *logger, raop_callbacks_t *callbacks, const c
|
|||||||
int remote_addr_len, unsigned short timing_rport,
|
int remote_addr_len, unsigned short timing_rport,
|
||||||
timing_protocol_t *time_protocol);
|
timing_protocol_t *time_protocol);
|
||||||
|
|
||||||
int airplay_video_service_init(raop_t *raop, unsigned short port, const char *lang, const char *session_id);
|
airplay_video_t *airplay_video_service_init(raop_t *raop, unsigned short port, const char *lang, const char *session_id);
|
||||||
bool register_airplay_video(raop_t *raop, airplay_video_t *airplay_video);
|
|
||||||
char *raop_get_lang(raop_t *raop);
|
char *raop_get_lang(raop_t *raop);
|
||||||
airplay_video_t *get_airplay_video(raop_t *raop);
|
|
||||||
airplay_video_t *deregister_airplay_video(raop_t *raop);
|
|
||||||
uint64_t get_local_time();
|
uint64_t get_local_time();
|
||||||
|
|
||||||
RAOP_API raop_t *raop_init(raop_callbacks_t *callbacks);
|
RAOP_API raop_t *raop_init(raop_callbacks_t *callbacks);
|
||||||
|
|||||||
Reference in New Issue
Block a user