mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
read language choice from setProperty?/MediaSelectionOptions
This commit is contained in:
@@ -39,6 +39,8 @@ struct airplay_video_s {
|
||||
char apple_session_id[37];
|
||||
char playback_uuid[37];
|
||||
char *uri_prefix;
|
||||
char *language_name;
|
||||
char *language_code;
|
||||
const char *lang;
|
||||
char local_uri_prefix[23];
|
||||
int next_uri;
|
||||
@@ -88,6 +90,10 @@ airplay_video_t *airplay_video_init(raop_t *raop, unsigned short http_port,
|
||||
|
||||
airplay_video->start_position_seconds = 0.0f;
|
||||
|
||||
airplay_video->uri_prefix = NULL;
|
||||
airplay_video->language_code = NULL;
|
||||
airplay_video->language_name = NULL;
|
||||
|
||||
airplay_video->media_data_store = NULL;
|
||||
airplay_video->master_playlist = NULL;
|
||||
airplay_video->num_uri = 0;
|
||||
@@ -103,6 +109,12 @@ airplay_video_destroy(airplay_video_t *airplay_video)
|
||||
if (airplay_video->uri_prefix) {
|
||||
free(airplay_video->uri_prefix);
|
||||
}
|
||||
if (airplay_video->language_name) {
|
||||
free(airplay_video->language_name);
|
||||
}
|
||||
if (airplay_video->language_code) {
|
||||
free(airplay_video->language_code);
|
||||
}
|
||||
if (airplay_video->media_data_store) {
|
||||
destroy_media_data_store(airplay_video);
|
||||
}
|
||||
@@ -152,7 +164,29 @@ void set_uri_prefix(airplay_video_t *airplay_video, char *uri_prefix) {
|
||||
}
|
||||
|
||||
const char *get_uri_prefix(airplay_video_t *airplay_video) {
|
||||
return airplay_video->uri_prefix;
|
||||
return (const char *) airplay_video->uri_prefix;
|
||||
}
|
||||
|
||||
void set_language_name(airplay_video_t *airplay_video, char *language_name) {
|
||||
if (airplay_video->language_name) {
|
||||
free (airplay_video->language_name);
|
||||
}
|
||||
airplay_video->language_name = language_name;
|
||||
}
|
||||
|
||||
const char *get_language_name(airplay_video_t *airplay_video) {
|
||||
return (const char *)airplay_video->language_name;
|
||||
}
|
||||
|
||||
void set_language_code(airplay_video_t *airplay_video, char *language_code) {
|
||||
if (airplay_video->language_code) {
|
||||
free (airplay_video->language_code);
|
||||
}
|
||||
airplay_video->language_code = language_code;
|
||||
}
|
||||
|
||||
const char *get_language_code(airplay_video_t *airplay_video) {
|
||||
return (const char *) airplay_video->language_code;
|
||||
}
|
||||
|
||||
char *get_uri_local_prefix(airplay_video_t *airplay_video) {
|
||||
|
||||
@@ -36,6 +36,10 @@ const char *get_playback_uuid(airplay_video_t *airplay_video);
|
||||
void set_uri_prefix(airplay_video_t *airplay_video, char *uri_prefix);
|
||||
const char *get_uri_prefix(airplay_video_t *airplay_video);
|
||||
char *get_uri_local_prefix(airplay_video_t *airplay_video);
|
||||
void set_language_code(airplay_video_t *airplay_video, char *language_code);
|
||||
const char *get_language_code(airplay_video_t *airplay_video);
|
||||
void set_language_name(airplay_video_t *airplay_video, char *language_name);
|
||||
const char *get_language_name(airplay_video_t *airplay_video);
|
||||
|
||||
int get_next_FCUP_RequestID(airplay_video_t *airplay_video);
|
||||
void set_next_media_uri_id(airplay_video_t *airplay_video, int id);
|
||||
|
||||
@@ -168,6 +168,7 @@ http_handler_set_property(raop_conn_t *conn,
|
||||
const char *property = url + strlen("/setProperty?");
|
||||
logger_log(conn->raop->logger, LOGGER_DEBUG, "http_handler_set_property: %s", property);
|
||||
|
||||
|
||||
/* actionAtItemEnd: values:
|
||||
0: advance (advance to next item, if there is one)
|
||||
1: pause (pause playing)
|
||||
@@ -175,9 +176,82 @@ http_handler_set_property(raop_conn_t *conn,
|
||||
|
||||
reverseEndTime (only used when rate < 0) time at which reverse playback ends
|
||||
forwardEndTime (only used when rate > 0) time at which reverse playback ends
|
||||
selectedMediaArray contains plist with language choice:
|
||||
*/
|
||||
|
||||
if (!strcmp(property, "reverseEndTime") ||
|
||||
airplay_video_t *airplay_video = conn->raop->airplay_video[conn->raop->current_video];
|
||||
if (!strcmp(property, "selectedMediaArray")) {
|
||||
/* verify that this request contains a binary plist*/
|
||||
char *header_str = NULL;
|
||||
int request_datalen = 0;
|
||||
http_request_get_header_string(request, &header_str);
|
||||
bool is_plist = strstr(header_str,"apple-binary-plist");
|
||||
free(header_str);
|
||||
if (!is_plist) {
|
||||
logger_log(conn->raop->logger, LOGGER_DEBUG, "POST /setProperty?selectedMediaArray"
|
||||
"does not provide an apple-binary-plist");
|
||||
goto post_error;
|
||||
}
|
||||
|
||||
const char *request_data = http_request_get_data(request, &request_datalen);
|
||||
plist_t req_root_node = NULL;
|
||||
plist_from_bin(request_data, request_datalen, &req_root_node);
|
||||
plist_t req_value_node = plist_dict_get_item(req_root_node, "value");
|
||||
|
||||
if (!req_value_node || !PLIST_IS_ARRAY(req_value_node)) {
|
||||
logger_log(conn->raop->logger, LOGGER_INFO, "POST /setProperty?selectedMediaArray"
|
||||
" did not provide expected plist from client");
|
||||
goto post_error;
|
||||
}
|
||||
|
||||
int count = plist_array_get_size(req_value_node);
|
||||
char *name = NULL;
|
||||
char *code = NULL;
|
||||
char *language_name = NULL;
|
||||
char *language_code = NULL;
|
||||
for (int i = 0; i < count; i++) {
|
||||
plist_t req_value_array_node = plist_array_get_item(req_value_node,i);
|
||||
if (!language_name) {
|
||||
plist_t req_value_options_name_node = plist_dict_get_item(req_value_array_node,"MediaSelectionOptionsName");
|
||||
if (PLIST_IS_STRING(req_value_options_name_node)) {
|
||||
plist_get_string_val(req_value_options_name_node, &name);
|
||||
if (name) {
|
||||
language_name = (char *) calloc(strlen(name) + 1, sizeof(char));
|
||||
memcpy(language_name, name, strlen(name));
|
||||
plist_mem_free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!language_code) {
|
||||
plist_t req_value_options_code_node = plist_dict_get_item(req_value_array_node,"MediaSelectionOptionsUnicodeLanguageIdentifier");
|
||||
if (PLIST_IS_STRING(req_value_options_code_node)) {
|
||||
plist_get_string_val(req_value_options_code_node, &code);
|
||||
if (code) {
|
||||
language_code = (char *) calloc(strlen(code) + 1, sizeof(char));
|
||||
memcpy(language_code, code, strlen(code));
|
||||
plist_mem_free(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (language_code && language_name) {
|
||||
break;
|
||||
} else {
|
||||
plist_free (req_value_array_node);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
plist_free (req_root_node);
|
||||
const char *lname = NULL, *lcode = NULL;
|
||||
if (language_code) {
|
||||
set_language_code(airplay_video, language_code);
|
||||
lcode = get_language_code(airplay_video);
|
||||
}
|
||||
if (language_name) {
|
||||
set_language_name(airplay_video, language_name);
|
||||
lname = get_language_name(airplay_video);
|
||||
}
|
||||
logger_log(conn->raop->logger, LOGGER_INFO, "stored language from MediaSelectionOptions: %s \"%s\"", lcode, lname);
|
||||
} else if (!strcmp(property, "reverseEndTime") ||
|
||||
!strcmp(property, "forwardEndTime") ||
|
||||
!strcmp(property, "actionAtItemEnd")) {
|
||||
logger_log(conn->raop->logger, LOGGER_DEBUG, "property %s is known but unhandled", property);
|
||||
@@ -190,8 +264,11 @@ http_handler_set_property(raop_conn_t *conn,
|
||||
http_response_add_header(response, "Content-Type", "text/x-apple-plist+xml");
|
||||
} else {
|
||||
logger_log(conn->raop->logger, LOGGER_DEBUG, "property %s is unknown, unhandled", property);
|
||||
http_response_add_header(response, "Content-Length", "0");
|
||||
goto post_error;
|
||||
}
|
||||
return;
|
||||
post_error:
|
||||
http_response_add_header(response, "Content-Length", "0");
|
||||
}
|
||||
|
||||
/* handles GET /getProperty http requests from Client to Server. (not implemented) */
|
||||
|
||||
Reference in New Issue
Block a user