mirror of
				https://github.com/owntone/owntone-server.git
				synced 2025-10-30 00:05:05 -04:00 
			
		
		
		
	[file/http/input] Implement metadata handling through input interface
This commit is contained in:
		
							parent
							
								
									0b9b008a1a
								
							
						
					
					
						commit
						8b5cac0538
					
				| @ -40,7 +40,7 @@ setup(struct player_source *ps) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| http_setup(struct player_source *ps) | setup_http(struct player_source *ps) | ||||||
| { | { | ||||||
|   char *url; |   char *url; | ||||||
| 
 | 
 | ||||||
| @ -103,6 +103,38 @@ seek(struct player_source *ps, int seek_ms) | |||||||
|   return transcode_seek(ps->xcode, seek_ms); |   return transcode_seek(ps->xcode, seek_ms); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int | ||||||
|  | metadata_get_http(struct input_metadata *metadata, struct player_source *ps) | ||||||
|  | { | ||||||
|  |   struct http_icy_metadata *m; | ||||||
|  |   int changed; | ||||||
|  | 
 | ||||||
|  |   m = transcode_metadata(ps->xcode, &changed); | ||||||
|  |   if (!m) | ||||||
|  |     return -1; | ||||||
|  | 
 | ||||||
|  |   if (!changed) | ||||||
|  |     { | ||||||
|  |       http_icy_metadata_free(m, 0); | ||||||
|  |       return -1; // TODO Perhaps a problem since this prohibits the player updating metadata
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   if (m->artist) | ||||||
|  |     metadata->artist = m->artist; | ||||||
|  |   // Note we map title to album, because clients should show stream name as titel
 | ||||||
|  |   if (m->title) | ||||||
|  |     metadata->album = m->title; | ||||||
|  |   if (m->artwork_url) | ||||||
|  |     metadata->artwork_url = m->artwork_url; | ||||||
|  | 
 | ||||||
|  |   m->artist = NULL; | ||||||
|  |   m->title = NULL; | ||||||
|  |   m->artwork_url = NULL; | ||||||
|  | 
 | ||||||
|  |   http_icy_metadata_free(m, 0); | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct input_definition input_file = | struct input_definition input_file = | ||||||
| { | { | ||||||
|   .name = "file", |   .name = "file", | ||||||
| @ -119,7 +151,8 @@ struct input_definition input_http = | |||||||
|   .name = "http", |   .name = "http", | ||||||
|   .type = INPUT_TYPE_HTTP, |   .type = INPUT_TYPE_HTTP, | ||||||
|   .disabled = 0, |   .disabled = 0, | ||||||
|   .setup = http_setup, |   .setup = setup_http, | ||||||
|   .start = start, |   .start = start, | ||||||
|   .stop = stop, |   .stop = stop, | ||||||
|  |   .metadata_get = metadata_get_http, | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -82,6 +82,9 @@ struct decode_ctx { | |||||||
|   // Duration (used to make wav header)
 |   // Duration (used to make wav header)
 | ||||||
|   uint32_t duration; |   uint32_t duration; | ||||||
| 
 | 
 | ||||||
|  |   // Data kind (used to determine if ICY metadata is relevant to look for)
 | ||||||
|  |   enum data_kind data_kind; | ||||||
|  | 
 | ||||||
|   // Contains the most recent packet from av_read_frame
 |   // Contains the most recent packet from av_read_frame
 | ||||||
|   // Used for resuming after seek and for freeing correctly
 |   // Used for resuming after seek and for freeing correctly
 | ||||||
|   // in transcode_decode()
 |   // in transcode_decode()
 | ||||||
| @ -583,7 +586,7 @@ flush_encoder(struct encode_ctx *ctx, unsigned int stream_index) | |||||||
| /* --------------------------- INPUT/OUTPUT INIT --------------------------- */ | /* --------------------------- INPUT/OUTPUT INIT --------------------------- */ | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| open_input(struct decode_ctx *ctx, enum data_kind data_kind, const char *path, int decode_video) | open_input(struct decode_ctx *ctx, const char *path, int decode_video) | ||||||
| { | { | ||||||
|   AVDictionary *options; |   AVDictionary *options; | ||||||
|   AVCodec *decoder; |   AVCodec *decoder; | ||||||
| @ -600,10 +603,10 @@ open_input(struct decode_ctx *ctx, enum data_kind data_kind, const char *path, i | |||||||
| 
 | 
 | ||||||
| # ifndef HAVE_FFMPEG | # ifndef HAVE_FFMPEG | ||||||
|   // Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
 |   // Without this, libav is slow to probe some internet streams, which leads to RAOP timeouts
 | ||||||
|   if (data_kind == DATA_KIND_HTTP) |   if (ctx->data_kind == DATA_KIND_HTTP) | ||||||
|     ctx->ifmt_ctx->probesize = 64000; |     ctx->ifmt_ctx->probesize = 64000; | ||||||
| # endif | # endif | ||||||
|   if (data_kind == DATA_KIND_HTTP) |   if (ctx->data_kind == DATA_KIND_HTTP) | ||||||
|     av_dict_set(&options, "icy", "1", 0); |     av_dict_set(&options, "icy", "1", 0); | ||||||
| 
 | 
 | ||||||
|   // TODO Newest versions of ffmpeg have timeout and reconnect options we should use
 |   // TODO Newest versions of ffmpeg have timeout and reconnect options we should use
 | ||||||
| @ -1245,14 +1248,15 @@ transcode_decode_setup(enum data_kind data_kind, const char *path, uint32_t song | |||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   if (open_input(ctx, data_kind, path, decode_video) < 0) |   ctx->duration = song_length; | ||||||
|  |   ctx->data_kind = data_kind; | ||||||
|  | 
 | ||||||
|  |   if (open_input(ctx, path, decode_video) < 0) | ||||||
|     { |     { | ||||||
|       free(ctx); |       free(ctx); | ||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   ctx->duration = song_length; |  | ||||||
| 
 |  | ||||||
|   av_init_packet(&ctx->packet); |   av_init_packet(&ctx->packet); | ||||||
| 
 | 
 | ||||||
|   return ctx; |   return ctx; | ||||||
| @ -1283,7 +1287,8 @@ transcode_encode_setup(struct decode_ctx *src_ctx, enum transcode_profile profil | |||||||
|       return NULL; |       return NULL; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   ctx->icy_interval = METADATA_ICY_INTERVAL * ctx->channels * ctx->byte_depth * ctx->sample_rate; |   if (src_ctx->data_kind == DATA_KIND_HTTP) | ||||||
|  |     ctx->icy_interval = METADATA_ICY_INTERVAL * ctx->channels * ctx->byte_depth * ctx->sample_rate; | ||||||
| 
 | 
 | ||||||
|   if (profile == XCODE_PCM16_HEADER) |   if (profile == XCODE_PCM16_HEADER) | ||||||
|     { |     { | ||||||
| @ -1637,6 +1642,8 @@ transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *ic | |||||||
|   int processed; |   int processed; | ||||||
|   int ret; |   int ret; | ||||||
| 
 | 
 | ||||||
|  |   *icy_timer = 0; | ||||||
|  | 
 | ||||||
|   processed = 0; |   processed = 0; | ||||||
|   while (processed < wanted) |   while (processed < wanted) | ||||||
|     { |     { | ||||||
| @ -1653,7 +1660,8 @@ transcode(struct evbuffer *evbuf, int wanted, struct transcode_ctx *ctx, int *ic | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   ctx->encode_ctx->total_bytes += processed; |   ctx->encode_ctx->total_bytes += processed; | ||||||
|   *icy_timer = (ctx->encode_ctx->total_bytes % ctx->encode_ctx->icy_interval < processed); |   if (ctx->encode_ctx->icy_interval) | ||||||
|  |     *icy_timer = (ctx->encode_ctx->total_bytes % ctx->encode_ctx->icy_interval < processed); | ||||||
| 
 | 
 | ||||||
|   return processed; |   return processed; | ||||||
| } | } | ||||||
| @ -1822,24 +1830,3 @@ transcode_metadata(struct transcode_ctx *ctx, int *changed) | |||||||
|   return m; |   return m; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| char * |  | ||||||
| transcode_metadata_artwork_url(struct transcode_ctx *ctx) |  | ||||||
| { |  | ||||||
|   struct http_icy_metadata *m; |  | ||||||
|   char *artwork_url; |  | ||||||
| 
 |  | ||||||
|   if (!ctx->decode_ctx->ifmt_ctx || !ctx->decode_ctx->ifmt_ctx->filename) |  | ||||||
|     return NULL; |  | ||||||
| 
 |  | ||||||
|   artwork_url = NULL; |  | ||||||
| 
 |  | ||||||
|   m = http_icy_metadata_get(ctx->decode_ctx->ifmt_ctx, 1); |  | ||||||
|   if (m && m->artwork_url) |  | ||||||
|     artwork_url = strdup(m->artwork_url); |  | ||||||
| 
 |  | ||||||
|   if (m) |  | ||||||
|     http_icy_metadata_free(m, 0); |  | ||||||
| 
 |  | ||||||
|   return artwork_url; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -100,7 +100,4 @@ transcode_seek(struct transcode_ctx *ctx, int ms); | |||||||
| struct http_icy_metadata * | struct http_icy_metadata * | ||||||
| transcode_metadata(struct transcode_ctx *ctx, int *changed); | transcode_metadata(struct transcode_ctx *ctx, int *changed); | ||||||
| 
 | 
 | ||||||
| char * |  | ||||||
| transcode_metadata_artwork_url(struct transcode_ctx *ctx); |  | ||||||
| 
 |  | ||||||
| #endif /* !__TRANSCODE_H__ */ | #endif /* !__TRANSCODE_H__ */ | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user