#pragma once #include "common.h" #include "config.h" #include #define number_of_watchers 2 typedef enum { PS_NOT_AVAILABLE = 0, PS_STOPPED, PS_PAUSED, PS_PLAYING, } play_status_type; typedef enum { AM_INACTIVE = 0, AM_ACTIVE, } active_state_type; typedef enum { SS_NOT_AVAILABLE = 0, SS_OFF, SS_ON, } shuffle_status_type; typedef enum { RS_NOT_AVAILABLE = 0, RS_OFF, RS_ONE, RS_ALL, } repeat_status_type; int string_update(char **str, int *changed, char *s); int int_update(int *receptacle, int *changed, int value); struct metadata_bundle; typedef void (*metadata_watcher)(struct metadata_bundle *argc, void *userdata); typedef struct metadata_bundle { char *client_ip; // IP number used by the audio source (i.e. the "client"), which is also the DACP // server int client_ip_changed; char *server_ip; // IP number used by Shairport Sync int server_ip_changed; char *progress_string; // progress string, emitted by the source from time to time int progress_string_changed; int player_thread_active; // true if a play thread is running int dacp_server_active; // true if there's a reachable DACP server (assumed to be the Airplay // client) ; false otherwise int advanced_dacp_server_active; // true if there's a reachable DACP server with iTunes // capabilitiues // ; false otherwise int dacp_server_has_been_active; // basically this is a delayed version of dacp_server_active, // used detect transitions between server activity being on or off // e.g. to reease metadata when a server goes inactive, but not if it's permanently // inactive. play_status_type play_status; shuffle_status_type shuffle_status; repeat_status_type repeat_status; // the following pertain to the track playing char *cover_art_pathname; int cover_art_pathname_changed; uint64_t item_id; // seems to be a track ID -- see itemid in DACP.c int item_id_changed; int item_id_received; // important for deciding if the track information should be ignored. unsigned char item_composite_id[16]; // seems to be nowplaying 4 ids: dbid, plid, playlistItem, itemid int item_composite_id_changed; char *track_name; int track_name_changed; char *artist_name; int artist_name_changed; char *album_artist_name; int album_artist_name_changed; char *album_name; int album_name_changed; char *genre; int genre_changed; char *comment; int comment_changed; char *composer; int composer_changed; char *file_kind; int file_kind_changed; char *song_description; int song_description_changed; char *song_album_artist; int song_album_artist_changed; char *sort_name; int sort_name_changed; char *sort_artist; int sort_artist_changed; char *sort_album; int sort_album_changed; char *sort_composer; int sort_composer_changed; uint32_t songtime_in_milliseconds; int songtime_in_milliseconds_changed; // end play_status_type player_state; // this is the state of the actual player itself, which can be a bit noisy. active_state_type active_state; int speaker_volume; // this is the actual speaker volume, allowing for the main volume and the // speaker volume control double airplay_volume; metadata_watcher watchers[number_of_watchers]; // functions to call if the metadata is changed. void *watchers_data[number_of_watchers]; // their individual data } metadata_bundle; extern struct metadata_bundle metadata_store; void add_metadata_watcher(metadata_watcher fn, void *userdata); void metadata_hub_init(void); void metadata_hub_stop(void); void metadata_hub_process_metadata(uint32_t type, uint32_t code, char *data, uint32_t length); void metadata_hub_reset_track_metadata(void); void metadata_hub_release_track_artwork(void); // these functions lock and unlock the read-write mutex on the metadata hub and run the watchers // afterwards void _metadata_hub_modify_prolog(const char *filename, const int linenumber); void _metadata_hub_modify_epilog(int modified, const char *filename, const int linenumber); // set to true if modifications occurred, 0 otherwise /* // these are for safe reading void _metadata_hub_read_prolog(const char *filename, const int linenumber); void _metadata_hub_read_epilog(const char *filename, const int linenumber); */ #define metadata_hub_modify_prolog(void) _metadata_hub_modify_prolog(__FILE__, __LINE__) #define metadata_hub_modify_epilog(modified) _metadata_hub_modify_epilog(modified, __FILE__, __LINE__) #define metadata_hub_read_prolog(void) _metadata_hub_read_prolog(__FILE__, __LINE__) #define metadata_hub_read_epilog(void) _metadata_hub_modify_epilog(__FILE__, __LINE__)