diff --git a/src/.gitignore b/src/.gitignore index d4434229..e5f056d7 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -11,3 +11,4 @@ RSP2SQL.[ch] daap_query_hash.c rsp_query_hash.c dacp_prop_hash.c +dmap_fields_hash.c diff --git a/src/Makefile.am b/src/Makefile.am index 740cc7b5..4978450b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,12 +24,14 @@ endif GPERF_FILES = \ daap_query.gperf \ rsp_query.gperf \ - dacp_prop.gperf + dacp_prop.gperf \ + dmap_fields.gperf GPERF_PRODUCTS = \ daap_query_hash.c \ rsp_query_hash.c \ - dacp_prop_hash.c + dacp_prop_hash.c \ + dmap_fields_hash.c ANTLR_GRAMMARS = \ RSP.g RSP2SQL.g \ diff --git a/src/dmap_fields.gperf b/src/dmap_fields.gperf new file mode 100644 index 00000000..db6fd642 --- /dev/null +++ b/src/dmap_fields.gperf @@ -0,0 +1,317 @@ +%language=ANSI-C +%readonly-tables +%enum +%switch=1 +%compare-lengths +%define hash-function-name dmap_hash_field +%define lookup-function-name dmap_find_field +%define slot-name desc +%global-table +%define word-array-name dmap_fields +%struct-type +%omit-struct-type +%{ +static const struct dmap_field_map dfm_dmap_miid = { dbmfi_offsetof(id), dbpli_offsetof(id), -1 }; +static const struct dmap_field_map dfm_dmap_minm = { dbmfi_offsetof(title), dbpli_offsetof(title), dbgri_offsetof(itemname) }; +static const struct dmap_field_map dfm_dmap_mikd = { dbmfi_offsetof(item_kind), -1, -1 }; +static const struct dmap_field_map dfm_dmap_mper = { dbmfi_offsetof(id), dbpli_offsetof(id), dbgri_offsetof(persistentid) }; +static const struct dmap_field_map dfm_dmap_mcon = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mcti = { dbmfi_offsetof(id), -1, -1 }; +static const struct dmap_field_map dfm_dmap_mpco = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mstt = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msts = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mimc = { dbmfi_offsetof(total_tracks), dbpli_offsetof(items), dbgri_offsetof(itemcount) }; +static const struct dmap_field_map dfm_dmap_mctc = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mrco = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mtco = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mlcl = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mlit = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mbcl = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mdcl = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msrv = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msau = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mslr = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mpro = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msal = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msup = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mspi = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msex = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msbr = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msqy = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msix = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msrs = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mstm = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_msdc = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mlog = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mlid = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mupd = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_musr = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_muty = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mudl = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mccr = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mcnm = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mcna = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_mcty = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_apro = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_avdb = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abro = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abal = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abar = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abcp = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abgn = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_adbs = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_asal = { dbmfi_offsetof(album), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asai = { dbmfi_offsetof(songalbumid), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asaa = { dbmfi_offsetof(album_artist), -1, dbgri_offsetof(songalbumartist) }; +static const struct dmap_field_map dfm_dmap_asar = { dbmfi_offsetof(artist), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asbt = { dbmfi_offsetof(bpm), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asbr = { dbmfi_offsetof(bitrate), -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascm = { dbmfi_offsetof(comment), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asco = { dbmfi_offsetof(compilation), -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascp = { dbmfi_offsetof(composer), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asda = { dbmfi_offsetof(time_added), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdm = { dbmfi_offsetof(time_modified), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdc = { dbmfi_offsetof(total_discs), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdn = { dbmfi_offsetof(disc), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdb = { dbmfi_offsetof(disabled), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aseq = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_asfm = { dbmfi_offsetof(type), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asgn = { dbmfi_offsetof(genre), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdt = { dbmfi_offsetof(description), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asrv = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_assr = { dbmfi_offsetof(samplerate), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assz = { dbmfi_offsetof(file_size), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asst = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_assp = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_astm = { dbmfi_offsetof(song_length), -1, -1 }; +static const struct dmap_field_map dfm_dmap_astc = { dbmfi_offsetof(total_tracks), -1, -1 }; +static const struct dmap_field_map dfm_dmap_astn = { dbmfi_offsetof(track), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asur = { dbmfi_offsetof(rating), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asyr = { dbmfi_offsetof(year), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdk = { dbmfi_offsetof(data_kind), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asul = { dbmfi_offsetof(url), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aply = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_abpl = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_apso = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_arsv = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_arif = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeNV = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSP = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aePS = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascd = { dbmfi_offsetof(codectype), -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascs = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_agrp = { dbmfi_offsetof(grouping), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSV = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aePI = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeCI = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeGI = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeAI = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSI = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSF = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascr = { dbmfi_offsetof(contentrating), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeHV = { dbmfi_offsetof(has_video), -1, -1 }; +static const struct dmap_field_map dfm_dmap_msas = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_asct = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_ascn = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aslc = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_asky = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_apsm = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aprm = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aePC = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aePP = { -1, -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeMK = { dbmfi_offsetof(media_kind), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeMk = { dbmfi_offsetof(media_kind), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSN = { dbmfi_offsetof(tv_series_name), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeNN = { dbmfi_offsetof(tv_network_name), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeEN = { dbmfi_offsetof(tv_episode_num_str), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeES = { dbmfi_offsetof(tv_episode_sort), -1, -1 }; +static const struct dmap_field_map dfm_dmap_aeSU = { dbmfi_offsetof(tv_season_num), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assn = { dbmfi_offsetof(title_sort), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assa = { dbmfi_offsetof(artist_sort), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assu = { dbmfi_offsetof(album_sort), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assc = { dbmfi_offsetof(composer_sort), -1, -1 }; +static const struct dmap_field_map dfm_dmap_assl = { dbmfi_offsetof(album_artist_sort), -1, -1 }; +%} +struct dmap_field; +%% +"daap.browsealbumlisting", "abal", &dfm_dmap_abal, DMAP_TYPE_LIST +"daap.browseartistlisting", "abar", &dfm_dmap_abar, DMAP_TYPE_LIST +"daap.browsecomposerlisting", "abcp", &dfm_dmap_abcp, DMAP_TYPE_LIST +"daap.browsegenrelisting", "abgn", &dfm_dmap_abgn, DMAP_TYPE_LIST +"daap.baseplaylist", "abpl", &dfm_dmap_abpl, DMAP_TYPE_UBYTE +"daap.databasebrowse", "abro", &dfm_dmap_abro, DMAP_TYPE_LIST +"daap.databasesongs", "adbs", &dfm_dmap_adbs, DMAP_TYPE_LIST +"com.apple.itunes.itms-artistid", "aeAI", &dfm_dmap_aeAI, DMAP_TYPE_UINT +"com.apple.itunes.itms-composerid", "aeCI", &dfm_dmap_aeCI, DMAP_TYPE_UINT +"com.apple.itunes.episode-num-str", "aeEN", &dfm_dmap_aeEN, DMAP_TYPE_STRING +"com.apple.itunes.episode-sort", "aeES", &dfm_dmap_aeES, DMAP_TYPE_UINT +"com.apple.itunes.itms-genreid", "aeGI", &dfm_dmap_aeGI, DMAP_TYPE_UINT +"com.apple.itunes.has-video", "aeHV", &dfm_dmap_aeHV, DMAP_TYPE_UBYTE +"com.apple.itunes.extended-media-kind", "aeMk", &dfm_dmap_aeMk, DMAP_TYPE_UINT +"com.apple.itunes.mediakind", "aeMK", &dfm_dmap_aeMK, DMAP_TYPE_UBYTE +"com.apple.itunes.network-name", "aeNN", &dfm_dmap_aeNN, DMAP_TYPE_STRING +"com.apple.itunes.norm-volume", "aeNV", &dfm_dmap_aeNV, DMAP_TYPE_UINT +"com.apple.itunes.is-podcast", "aePC", &dfm_dmap_aePC, DMAP_TYPE_UBYTE +"com.apple.itunes.itms-playlistid", "aePI", &dfm_dmap_aePI, DMAP_TYPE_UINT +"com.apple.itunes.is-podcast-playlist", "aePP", &dfm_dmap_aePP, DMAP_TYPE_UBYTE +"com.apple.itunes.special-playlist", "aePS", &dfm_dmap_aePS, DMAP_TYPE_UBYTE +"com.apple.itunes.itms-storefrontid", "aeSF", &dfm_dmap_aeSF, DMAP_TYPE_UINT +"com.apple.itunes.itms-songid", "aeSI", &dfm_dmap_aeSI, DMAP_TYPE_UINT +"com.apple.itunes.series-name", "aeSN", &dfm_dmap_aeSN, DMAP_TYPE_STRING +"com.apple.itunes.smart-playlist", "aeSP", &dfm_dmap_aeSP, DMAP_TYPE_UBYTE +"com.apple.itunes.season-num", "aeSU", &dfm_dmap_aeSU, DMAP_TYPE_UINT +"com.apple.itunes.music-sharing-version", "aeSV", &dfm_dmap_aeSV, DMAP_TYPE_UINT +"daap.songgrouping", "agrp", &dfm_dmap_agrp, DMAP_TYPE_STRING +"daap.databaseplaylists", "aply", &dfm_dmap_aply, DMAP_TYPE_LIST +"daap.playlistrepeatmode", "aprm", &dfm_dmap_aprm, DMAP_TYPE_UBYTE +"daap.protocolversion", "apro", &dfm_dmap_apro, DMAP_TYPE_VERSION +"daap.playlistshufflemode", "apsm", &dfm_dmap_apsm, DMAP_TYPE_UBYTE +"daap.playlistsongs", "apso", &dfm_dmap_apso, DMAP_TYPE_LIST +"daap.resolveinfo", "arif", &dfm_dmap_arif, DMAP_TYPE_LIST +"daap.resolve", "arsv", &dfm_dmap_arsv, DMAP_TYPE_LIST +"daap.songalbumartist", "asaa", &dfm_dmap_asaa, DMAP_TYPE_STRING +"daap.songalbumid", "asai", &dfm_dmap_asai, DMAP_TYPE_ULONG +"daap.songalbum", "asal", &dfm_dmap_asal, DMAP_TYPE_STRING +"daap.songartist", "asar", &dfm_dmap_asar, DMAP_TYPE_STRING +"daap.songbitrate", "asbr", &dfm_dmap_asbr, DMAP_TYPE_USHORT +"daap.songbeatsperminute", "asbt", &dfm_dmap_asbt, DMAP_TYPE_USHORT +"daap.songcodectype", "ascd", &dfm_dmap_ascd, DMAP_TYPE_UINT +"daap.songcomment", "ascm", &dfm_dmap_ascm, DMAP_TYPE_STRING +"daap.songcontentdescription", "ascn", &dfm_dmap_ascn, DMAP_TYPE_STRING +"daap.songcompilation", "asco", &dfm_dmap_asco, DMAP_TYPE_UBYTE +"daap.songcomposer", "ascp", &dfm_dmap_ascp, DMAP_TYPE_STRING +"daap.songcontentrating", "ascr", &dfm_dmap_ascr, DMAP_TYPE_UBYTE +"daap.songcodecsubtype", "ascs", &dfm_dmap_ascs, DMAP_TYPE_UINT +"daap.songcategory", "asct", &dfm_dmap_asct, DMAP_TYPE_STRING +"daap.songdateadded", "asda", &dfm_dmap_asda, DMAP_TYPE_DATE +"daap.songdisabled", "asdb", &dfm_dmap_asdb, DMAP_TYPE_UBYTE +"daap.songdisccount", "asdc", &dfm_dmap_asdc, DMAP_TYPE_USHORT +"daap.songdatakind", "asdk", &dfm_dmap_asdk, DMAP_TYPE_UBYTE +"daap.songdatemodified", "asdm", &dfm_dmap_asdm, DMAP_TYPE_DATE +"daap.songdiscnumber", "asdn", &dfm_dmap_asdn, DMAP_TYPE_USHORT +"daap.songdescription", "asdt", &dfm_dmap_asdt, DMAP_TYPE_STRING +"daap.songeqpreset", "aseq", &dfm_dmap_aseq, DMAP_TYPE_STRING +"daap.songformat", "asfm", &dfm_dmap_asfm, DMAP_TYPE_STRING +"daap.songgenre", "asgn", &dfm_dmap_asgn, DMAP_TYPE_STRING +"daap.songkeywords", "asky", &dfm_dmap_asky, DMAP_TYPE_STRING +"daap.songlongcontentdescription", "aslc", &dfm_dmap_aslc, DMAP_TYPE_STRING +"daap.songrelativevolume", "asrv", &dfm_dmap_asrv, DMAP_TYPE_BYTE +"daap.sortartist", "assa", &dfm_dmap_assa, DMAP_TYPE_STRING +"daap.sortcomposer", "assc", &dfm_dmap_assc, DMAP_TYPE_STRING +"daap.sortalbumartist", "assl", &dfm_dmap_assl, DMAP_TYPE_STRING +"daap.sortname", "assn", &dfm_dmap_assn, DMAP_TYPE_STRING +"daap.songstoptime", "assp", &dfm_dmap_assp, DMAP_TYPE_UINT +"daap.songsamplerate", "assr", &dfm_dmap_assr, DMAP_TYPE_UINT +"daap.songstarttime", "asst", &dfm_dmap_asst, DMAP_TYPE_UINT +"daap.sortalbum", "assu", &dfm_dmap_assu, DMAP_TYPE_STRING +"daap.songsize", "assz", &dfm_dmap_assz, DMAP_TYPE_UINT +"daap.songtrackcount", "astc", &dfm_dmap_astc, DMAP_TYPE_USHORT +"daap.songtime", "astm", &dfm_dmap_astm, DMAP_TYPE_UINT +"daap.songtracknumber", "astn", &dfm_dmap_astn, DMAP_TYPE_USHORT +"daap.songdataurl", "asul", &dfm_dmap_asul, DMAP_TYPE_STRING +"daap.songuserrating", "asur", &dfm_dmap_asur, DMAP_TYPE_UBYTE +"daap.songyear", "asyr", &dfm_dmap_asyr, DMAP_TYPE_USHORT +"daap.serverdatabases", "avdb", &dfm_dmap_avdb, DMAP_TYPE_LIST +"dmap.bag", "mbcl", &dfm_dmap_mbcl, DMAP_TYPE_LIST +"dmap.contentcodesresponse", "mccr", &dfm_dmap_mccr, DMAP_TYPE_LIST +"dmap.contentcodesname", "mcna", &dfm_dmap_mcna, DMAP_TYPE_STRING +"dmap.contentcodesnumber", "mcnm", &dfm_dmap_mcnm, DMAP_TYPE_UINT +"dmap.container", "mcon", &dfm_dmap_mcon, DMAP_TYPE_LIST +"dmap.containercount", "mctc", &dfm_dmap_mctc, DMAP_TYPE_UINT +"dmap.containeritemid", "mcti", &dfm_dmap_mcti, DMAP_TYPE_UINT +"dmap.contentcodestype", "mcty", &dfm_dmap_mcty, DMAP_TYPE_USHORT +"dmap.dictionary", "mdcl", &dfm_dmap_mdcl, DMAP_TYPE_LIST +"dmap.itemid", "miid", &dfm_dmap_miid, DMAP_TYPE_UINT +"dmap.itemkind", "mikd", &dfm_dmap_mikd, DMAP_TYPE_UBYTE +"dmap.itemcount", "mimc", &dfm_dmap_mimc, DMAP_TYPE_UINT +"dmap.itemname", "minm", &dfm_dmap_minm, DMAP_TYPE_STRING +"dmap.listing", "mlcl", &dfm_dmap_mlcl, DMAP_TYPE_LIST +"dmap.sessionid", "mlid", &dfm_dmap_mlid, DMAP_TYPE_UINT +"dmap.listingitem", "mlit", &dfm_dmap_mlit, DMAP_TYPE_LIST +"dmap.loginresponse", "mlog", &dfm_dmap_mlog, DMAP_TYPE_LIST +"dmap.parentcontainerid", "mpco", &dfm_dmap_mpco, DMAP_TYPE_UINT +"dmap.persistentid", "mper", &dfm_dmap_mper, DMAP_TYPE_ULONG +"dmap.protocolversion", "mpro", &dfm_dmap_mpro, DMAP_TYPE_VERSION +"dmap.returnedcount", "mrco", &dfm_dmap_mrco, DMAP_TYPE_UINT +"dmap.supportsautologout", "msal", &dfm_dmap_msal, DMAP_TYPE_UBYTE +"dmap.authenticationschemes", "msas", &dfm_dmap_msas, DMAP_TYPE_UINT +"dmap.authenticationmethod", "msau", &dfm_dmap_msau, DMAP_TYPE_UBYTE +"dmap.supportsbrowse", "msbr", &dfm_dmap_msbr, DMAP_TYPE_UBYTE +"dmap.databasescount", "msdc", &dfm_dmap_msdc, DMAP_TYPE_UINT +"dmap.supportsextensions", "msex", &dfm_dmap_msex, DMAP_TYPE_UBYTE +"dmap.supportsindex", "msix", &dfm_dmap_msix, DMAP_TYPE_UBYTE +"dmap.loginrequired", "mslr", &dfm_dmap_mslr, DMAP_TYPE_UBYTE +"dmap.supportspersistentids", "mspi", &dfm_dmap_mspi, DMAP_TYPE_UBYTE +"dmap.supportsquery", "msqy", &dfm_dmap_msqy, DMAP_TYPE_UBYTE +"dmap.supportsresolve", "msrs", &dfm_dmap_msrs, DMAP_TYPE_UBYTE +"dmap.serverinforesponse", "msrv", &dfm_dmap_msrv, DMAP_TYPE_LIST +"dmap.timeoutinterval", "mstm", &dfm_dmap_mstm, DMAP_TYPE_UINT +"dmap.statusstring", "msts", &dfm_dmap_msts, DMAP_TYPE_STRING +"dmap.status", "mstt", &dfm_dmap_mstt, DMAP_TYPE_UINT +"dmap.supportsupdate", "msup", &dfm_dmap_msup, DMAP_TYPE_UBYTE +"dmap.specifiedtotalcount", "mtco", &dfm_dmap_mtco, DMAP_TYPE_UINT +"dmap.deletedidlisting", "mudl", &dfm_dmap_mudl, DMAP_TYPE_LIST +"dmap.updateresponse", "mupd", &dfm_dmap_mupd, DMAP_TYPE_LIST +"dmap.serverrevision", "musr", &dfm_dmap_musr, DMAP_TYPE_UINT +"dmap.updatetype", "muty", &dfm_dmap_muty, DMAP_TYPE_UBYTE +%% +/* Sort fields */ +/* +"dmap.sortingheaderlisting", "mshl", &dfm_dmap_mshl, DMAP_TYPE_UINT +"dmap.sortingheaderchar", "mshc", &dfm_dmap_mshc, DMAP_TYPE_SHORT +"dmap.sortingheaderindex", "mshi", &dfm_dmap_mshi, DMAP_TYPE_UINT +"dmap.sortingheadernumber", "mshn", &dfm_dmap_mshn, DMAP_TYPE_UINT +*/ +/* Unsupported DMAP fields */ + +/* +"com.apple.itunes.adam-ids-array", "aeAD", &dfm_dmap_aeAD, DMAP_TYPE_LIST +"com.apple.itunes.content-rating", "aeCR", &dfm_dmap_aeCR, DMAP_TYPE_STRING +"com.apple.itunes.drm-platform-id", "aeDP", &dfm_dmap_aeDP, DMAP_TYPE_UINT +"com.apple.itunes.drm-user-id", "aeDR", &dfm_dmap_aeDR, DMAP_TYPE_ULONG +"com.apple.itunes.drm-versions", "aeDV", &dfm_dmap_aeDV, DMAP_TYPE_UINT +"com.apple.itunes.gapless-enc-dr", "aeGD", &dfm_dmap_aeGD, DMAP_TYPE_UINT +"com.apple.itunes.gapless-enc-del", "aeGE", &dfm_dmap_aeGE, DMAP_TYPE_UINT +"com.apple.itunes.gapless-heur", "aeGH", &dfm_dmap_aeGH, DMAP_TYPE_UINT +"com.apple.itunes.gapless-resy", "aeGR", &dfm_dmap_aeGR, DMAP_TYPE_ULONG +"com.apple.itunes.gapless-dur", "aeGU", &dfm_dmap_aeGU, DMAP_TYPE_ULONG +"com.apple.itunes.is-hd-video", "aeHD", &dfm_dmap_aeHD, DMAP_TYPE_UBYTE +"com.apple.itunes.drm-key1-id", "aeK1", &dfm_dmap_aeK1, DMAP_TYPE_ULONG +"com.apple.itunes.drm-key2-id", "aeK2", &dfm_dmap_aeK2, DMAP_TYPE_ULONG +"com.apple.itunes.non-drm-user-id", "aeND", &dfm_dmap_aeND, DMAP_TYPE_ULONG +"com.apple.itunes.store-pers-id", "aeSE", &dfm_dmap_aeSE, DMAP_TYPE_ULONG +"com.apple.itunes.saved-genius", "aeSG", &dfm_dmap_aeSG, DMAP_TYPE_UBYTE +"com.apple.itunes.xid", "aeXD", &dfm_dmap_aeXD, DMAP_TYPE_STRING +"daap.bookmarkable", "asbk", &dfm_dmap_asbk, DMAP_TYPE_UBYTE +"daap.songbookmark", "asbo", &dfm_dmap_asbo, DMAP_TYPE_UINT +"daap.songdatepurchased", "asdp", &dfm_dmap_asdp, DMAP_TYPE_DATE +"daap.songdatereleased", "asdr", &dfm_dmap_asdr, DMAP_TYPE_DATE +"daap.songextradata", "ased", &dfm_dmap_ased, DMAP_TYPE_USHORT +"daap.songgapless", "asgp", &dfm_dmap_asgp, DMAP_TYPE_UBYTE +"daap.songhasbeenplayed", "ashp", &dfm_dmap_ashp, DMAP_TYPE_UBYTE +"daap.songlongsize", "asls", &dfm_dmap_asls, DMAP_TYPE_ULONG +"daap.songpodcasturl", "aspu", &dfm_dmap_aspu, DMAP_TYPE_STRING +"daap.sortseriesname", "asss", &dfm_dmap_asss, DMAP_TYPE_STRING +"daap.supportsextradata", "ated", &dfm_dmap_ated, DMAP_TYPE_USHORT +"com.apple.itunes.jukebox-client-vote", "ceJC", &dfm_dmap_ceJC, DMAP_TYPE_BYTE +"com.apple.itunes.jukebox-current", "ceJI", &dfm_dmap_ceJI, DMAP_TYPE_UINT +"com.apple.itunes.jukebox-score", "ceJS", &dfm_dmap_ceJS, DMAP_TYPE_SHORT +"com.apple.itunes.jukebox-vote", "ceJV", &dfm_dmap_ceJV, DMAP_TYPE_UINT +"dmap.editcommandssupported", "meds", &dfm_dmap_meds, DMAP_TYPE_UINT +"dmap.utctime", "mstc", &dfm_dmap_mstc, DMAP_TYPE_DATE +"dmap.utcoffset", "msto", &dfm_dmap_msto, DMAP_TYPE_INT +*/ + +/* DMAP test fields */ +/* +"test.container", "TEST", &dfm_dmap_TEST, DMAP_TYPE_LIST +"test.ubyte", "TST1", &dfm_dmap_TST1, DMAP_TYPE_UBYTE +"test.byte", "TST2", &dfm_dmap_TST2, DMAP_TYPE_BYTE +"test.ushort", "TST3", &dfm_dmap_TST3, DMAP_TYPE_USHORT +"test.short", "TST4", &dfm_dmap_TST4, DMAP_TYPE_SHORT +"test.uint", "TST5", &dfm_dmap_TST5, DMAP_TYPE_UINT +"test.int", "TST6", &dfm_dmap_TST6, DMAP_TYPE_INT +"test.ulong", "TST7", &dfm_dmap_TST7, DMAP_TYPE_ULONG +"test.long", "TST8", &dfm_dmap_TST8, DMAP_TYPE_LONG +"test.string", "TST9", &dfm_dmap_TST9, DMAP_TYPE_STRING +*/ diff --git a/src/httpd_daap.c b/src/httpd_daap.c index abe08f0d..3eeb9e54 100644 --- a/src/httpd_daap.c +++ b/src/httpd_daap.c @@ -79,20 +79,19 @@ struct daap_update_request { struct daap_update_request *next; }; -struct dmap_field { - char *tag; - char *desc; - enum dmap_type type; -}; - struct dmap_field_map { - uint32_t hash; - const struct dmap_field *field; ssize_t mfi_offset; ssize_t pli_offset; ssize_t gri_offset; }; +struct dmap_field { + char *desc; + char *tag; + const struct dmap_field_map *dfm; + enum dmap_type type; +}; + struct sort_ctx { struct evbuffer *headerlist; int16_t mshc; @@ -102,433 +101,14 @@ struct sort_ctx { }; -static const struct dmap_field dmap_abal = { "abal", "daap.browsealbumlisting", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_abar = { "abar", "daap.browseartistlisting", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_abcp = { "abcp", "daap.browsecomposerlisting", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_abgn = { "abgn", "daap.browsegenrelisting", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_abpl = { "abpl", "daap.baseplaylist", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_abro = { "abro", "daap.databasebrowse", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_adbs = { "adbs", "daap.databasesongs", DMAP_TYPE_LIST }; -//static const struct dmap_field dmap_aeAD = { "aeAD", "com.apple.itunes.adam-ids-array", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_aeAI = { "aeAI", "com.apple.itunes.itms-artistid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeCI = { "aeCI", "com.apple.itunes.itms-composerid", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeCR = { "aeCR", "com.apple.itunes.content-rating", DMAP_TYPE_STRING }; -//static const struct dmap_field dmap_aeDP = { "aeDP", "com.apple.itunes.drm-platform-id", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeDR = { "aeDR", "com.apple.itunes.drm-user-id", DMAP_TYPE_ULONG }; -//static const struct dmap_field dmap_aeDV = { "aeDV", "com.apple.itunes.drm-versions", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeEN = { "aeEN", "com.apple.itunes.episode-num-str", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_aeES = { "aeES", "com.apple.itunes.episode-sort", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeGD = { "aeGD", "com.apple.itunes.gapless-enc-dr", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeGE = { "aeGE", "com.apple.itunes.gapless-enc-del", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeGH = { "aeGH", "com.apple.itunes.gapless-heur", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeGI = { "aeGI", "com.apple.itunes.itms-genreid", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeGR = { "aeGR", "com.apple.itunes.gapless-resy", DMAP_TYPE_ULONG }; -//static const struct dmap_field dmap_aeGU = { "aeGU", "com.apple.itunes.gapless-dur", DMAP_TYPE_ULONG }; -//static const struct dmap_field dmap_aeHD = { "aeHD", "com.apple.itunes.is-hd-video", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_aeHV = { "aeHV", "com.apple.itunes.has-video", DMAP_TYPE_UBYTE }; -//static const struct dmap_field dmap_aeK1 = { "aeK1", "com.apple.itunes.drm-key1-id", DMAP_TYPE_ULONG }; -//static const struct dmap_field dmap_aeK2 = { "aeK2", "com.apple.itunes.drm-key2-id", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_aeMk = { "aeMk", "com.apple.itunes.extended-media-kind", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeMK = { "aeMK", "com.apple.itunes.mediakind", DMAP_TYPE_UBYTE }; -//static const struct dmap_field dmap_aeND = { "aeND", "com.apple.itunes.non-drm-user-id", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_aeNN = { "aeNN", "com.apple.itunes.network-name", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_aeNV = { "aeNV", "com.apple.itunes.norm-volume", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aePC = { "aePC", "com.apple.itunes.is-podcast", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_aePI = { "aePI", "com.apple.itunes.itms-playlistid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aePP = { "aePP", "com.apple.itunes.is-podcast-playlist", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_aePS = { "aePS", "com.apple.itunes.special-playlist", DMAP_TYPE_UBYTE }; -//static const struct dmap_field dmap_aeSE = { "aeSE", "com.apple.itunes.store-pers-id", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_aeSF = { "aeSF", "com.apple.itunes.itms-storefrontid", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeSG = { "aeSG", "com.apple.itunes.saved-genius", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_aeSI = { "aeSI", "com.apple.itunes.itms-songid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeSN = { "aeSN", "com.apple.itunes.series-name", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_aeSP = { "aeSP", "com.apple.itunes.smart-playlist", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_aeSU = { "aeSU", "com.apple.itunes.season-num", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_aeSV = { "aeSV", "com.apple.itunes.music-sharing-version", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_aeXD = { "aeXD", "com.apple.itunes.xid", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_agrp = { "agrp", "daap.songgrouping", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_aply = { "aply", "daap.databaseplaylists", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_aprm = { "aprm", "daap.playlistrepeatmode", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_apro = { "apro", "daap.protocolversion", DMAP_TYPE_VERSION }; -static const struct dmap_field dmap_apsm = { "apsm", "daap.playlistshufflemode", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_apso = { "apso", "daap.playlistsongs", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_arif = { "arif", "daap.resolveinfo", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_arsv = { "arsv", "daap.resolve", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_asaa = { "asaa", "daap.songalbumartist", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asai = { "asai", "daap.songalbumid", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_asal = { "asal", "daap.songalbum", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asar = { "asar", "daap.songartist", DMAP_TYPE_STRING }; -//static const struct dmap_field dmap_asbk = { "asbk", "daap.bookmarkable", DMAP_TYPE_UBYTE }; -//static const struct dmap_field dmap_asbo = { "asbo", "daap.songbookmark", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_asbr = { "asbr", "daap.songbitrate", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_asbt = { "asbt", "daap.songbeatsperminute", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_ascd = { "ascd", "daap.songcodectype", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_ascm = { "ascm", "daap.songcomment", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_ascn = { "ascn", "daap.songcontentdescription", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asco = { "asco", "daap.songcompilation", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_ascp = { "ascp", "daap.songcomposer", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_ascr = { "ascr", "daap.songcontentrating", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_ascs = { "ascs", "daap.songcodecsubtype", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_asct = { "asct", "daap.songcategory", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asda = { "asda", "daap.songdateadded", DMAP_TYPE_DATE }; -static const struct dmap_field dmap_asdb = { "asdb", "daap.songdisabled", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_asdc = { "asdc", "daap.songdisccount", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_asdk = { "asdk", "daap.songdatakind", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_asdm = { "asdm", "daap.songdatemodified", DMAP_TYPE_DATE }; -static const struct dmap_field dmap_asdn = { "asdn", "daap.songdiscnumber", DMAP_TYPE_USHORT }; -//static const struct dmap_field dmap_asdp = { "asdp", "daap.songdatepurchased", DMAP_TYPE_DATE }; -//static const struct dmap_field dmap_asdr = { "asdr", "daap.songdatereleased", DMAP_TYPE_DATE }; -static const struct dmap_field dmap_asdt = { "asdt", "daap.songdescription", DMAP_TYPE_STRING }; -//static const struct dmap_field dmap_ased = { "ased", "daap.songextradata", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_aseq = { "aseq", "daap.songeqpreset", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asfm = { "asfm", "daap.songformat", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asgn = { "asgn", "daap.songgenre", DMAP_TYPE_STRING }; -//static const struct dmap_field dmap_asgp = { "asgp", "daap.songgapless", DMAP_TYPE_UBYTE }; -//static const struct dmap_field dmap_ashp = { "ashp", "daap.songhasbeenplayed", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_asky = { "asky", "daap.songkeywords", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_aslc = { "aslc", "daap.songlongcontentdescription", DMAP_TYPE_STRING }; -//static const struct dmap_field dmap_asls = { "asls", "daap.songlongsize", DMAP_TYPE_ULONG }; -//static const struct dmap_field dmap_aspu = { "aspu", "daap.songpodcasturl", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asrv = { "asrv", "daap.songrelativevolume", DMAP_TYPE_BYTE }; -static const struct dmap_field dmap_assa = { "assa", "daap.sortartist", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_assc = { "assc", "daap.sortcomposer", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_assl = { "assl", "daap.sortalbumartist", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_assn = { "assn", "daap.sortname", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_assp = { "assp", "daap.songstoptime", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_assr = { "assr", "daap.songsamplerate", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_asss = { "asss", "daap.sortseriesname", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asst = { "asst", "daap.songstarttime", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_assu = { "assu", "daap.sortalbum", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_assz = { "assz", "daap.songsize", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_astc = { "astc", "daap.songtrackcount", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_astm = { "astm", "daap.songtime", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_astn = { "astn", "daap.songtracknumber", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_asul = { "asul", "daap.songdataurl", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_asur = { "asur", "daap.songuserrating", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_asyr = { "asyr", "daap.songyear", DMAP_TYPE_USHORT }; -//static const struct dmap_field dmap_ated = { "ated", "daap.supportsextradata", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_avdb = { "avdb", "daap.serverdatabases", DMAP_TYPE_LIST }; -//static const struct dmap_field dmap_ceJC = { "ceJC", "com.apple.itunes.jukebox-client-vote", DMAP_TYPE_BYTE }; -//static const struct dmap_field dmap_ceJI = { "ceJI", "com.apple.itunes.jukebox-current", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_ceJS = { "ceJS", "com.apple.itunes.jukebox-score", DMAP_TYPE_SHORT }; -//static const struct dmap_field dmap_ceJV = { "ceJV", "com.apple.itunes.jukebox-vote", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mbcl = { "mbcl", "dmap.bag", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mccr = { "mccr", "dmap.contentcodesresponse", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mcna = { "mcna", "dmap.contentcodesname", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_mcnm = { "mcnm", "dmap.contentcodesnumber", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mcon = { "mcon", "dmap.container", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mctc = { "mctc", "dmap.containercount", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mcti = { "mcti", "dmap.containeritemid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mcty = { "mcty", "dmap.contentcodestype", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_mdcl = { "mdcl", "dmap.dictionary", DMAP_TYPE_LIST }; -//static const struct dmap_field dmap_meds = { "meds", "dmap.editcommandssupported", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_miid = { "miid", "dmap.itemid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mikd = { "mikd", "dmap.itemkind", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_mimc = { "mimc", "dmap.itemcount", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_minm = { "minm", "dmap.itemname", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_mlcl = { "mlcl", "dmap.listing", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mlid = { "mlid", "dmap.sessionid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mlit = { "mlit", "dmap.listingitem", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mlog = { "mlog", "dmap.loginresponse", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mpco = { "mpco", "dmap.parentcontainerid", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mper = { "mper", "dmap.persistentid", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_mpro = { "mpro", "dmap.protocolversion", DMAP_TYPE_VERSION }; -static const struct dmap_field dmap_mrco = { "mrco", "dmap.returnedcount", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_msal = { "msal", "dmap.supportsautologout", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msas = { "msas", "dmap.authenticationschemes", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_msau = { "msau", "dmap.authenticationmethod", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msbr = { "msbr", "dmap.supportsbrowse", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msdc = { "msdc", "dmap.databasescount", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mshl = { "mshl", "dmap.sortingheaderlisting", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mshc = { "mshc", "dmap.sortingheaderchar", DMAP_TYPE_SHORT }; -static const struct dmap_field dmap_mshi = { "mshi", "dmap.sortingheaderindex", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mshn = { "mshn", "dmap.sortingheadernumber", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_msex = { "msex", "dmap.supportsextensions", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msix = { "msix", "dmap.supportsindex", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_mslr = { "mslr", "dmap.loginrequired", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_mspi = { "mspi", "dmap.supportspersistentids", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msqy = { "msqy", "dmap.supportsquery", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msrs = { "msrs", "dmap.supportsresolve", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_msrv = { "msrv", "dmap.serverinforesponse", DMAP_TYPE_LIST }; -//static const struct dmap_field dmap_mstc = { "mstc", "dmap.utctime", DMAP_TYPE_DATE }; -static const struct dmap_field dmap_mstm = { "mstm", "dmap.timeoutinterval", DMAP_TYPE_UINT }; -//static const struct dmap_field dmap_msto = { "msto", "dmap.utcoffset", DMAP_TYPE_INT }; -static const struct dmap_field dmap_msts = { "msts", "dmap.statusstring", DMAP_TYPE_STRING }; -static const struct dmap_field dmap_mstt = { "mstt", "dmap.status", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_msup = { "msup", "dmap.supportsupdate", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_mtco = { "mtco", "dmap.specifiedtotalcount", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_mudl = { "mudl", "dmap.deletedidlisting", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_mupd = { "mupd", "dmap.updateresponse", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_musr = { "musr", "dmap.serverrevision", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_muty = { "muty", "dmap.updatetype", DMAP_TYPE_UBYTE }; - -static struct dmap_field_map dmap_fields[] = - { - { 0, &dmap_miid, - dbmfi_offsetof(id), dbpli_offsetof(id), -1 }, - { 0, &dmap_minm, - dbmfi_offsetof(title), dbpli_offsetof(title), dbgri_offsetof(itemname) }, - { 0, &dmap_mikd, - dbmfi_offsetof(item_kind), -1, -1 }, - { 0, &dmap_mper, - dbmfi_offsetof(id), dbpli_offsetof(id), dbgri_offsetof(persistentid) }, - { 0, &dmap_mcon, - -1, -1, -1 }, - { 0, &dmap_mcti, - dbmfi_offsetof(id), -1, -1 }, - { 0, &dmap_mpco, - -1, -1, -1 }, - { 0, &dmap_mstt, - -1, -1, -1 }, - { 0, &dmap_msts, - -1, -1, -1 }, - { 0, &dmap_mimc, - dbmfi_offsetof(total_tracks), dbpli_offsetof(items), dbgri_offsetof(itemcount) }, - { 0, &dmap_mctc, - -1, -1, -1 }, - { 0, &dmap_mrco, - -1, -1, -1 }, - { 0, &dmap_mtco, - -1, -1, -1 }, - { 0, &dmap_mlcl, - -1, -1, -1 }, - { 0, &dmap_mlit, - -1, -1, -1 }, - { 0, &dmap_mbcl, - -1, -1, -1 }, - { 0, &dmap_mdcl, - -1, -1, -1 }, - { 0, &dmap_msrv, - -1, -1, -1 }, - { 0, &dmap_msau, - -1, -1, -1 }, - { 0, &dmap_mslr, - -1, -1, -1 }, - { 0, &dmap_mpro, - -1, -1, -1 }, - { 0, &dmap_msal, - -1, -1, -1 }, - { 0, &dmap_msup, - -1, -1, -1 }, - { 0, &dmap_mspi, - -1, -1, -1 }, - { 0, &dmap_msex, - -1, -1, -1 }, - { 0, &dmap_msbr, - -1, -1, -1 }, - { 0, &dmap_msqy, - -1, -1, -1 }, - { 0, &dmap_msix, - -1, -1, -1 }, - { 0, &dmap_msrs, - -1, -1, -1 }, - { 0, &dmap_mstm, - -1, -1, -1 }, - { 0, &dmap_msdc, - -1, -1, -1 }, - { 0, &dmap_mlog, - -1, -1, -1 }, - { 0, &dmap_mlid, - -1, -1, -1 }, - { 0, &dmap_mupd, - -1, -1, -1 }, - { 0, &dmap_musr, - -1, -1, -1 }, - { 0, &dmap_muty, - -1, -1, -1 }, - { 0, &dmap_mudl, - -1, -1, -1 }, - { 0, &dmap_mccr, - -1, -1, -1 }, - { 0, &dmap_mcnm, - -1, -1, -1 }, - { 0, &dmap_mcna, - -1, -1, -1 }, - { 0, &dmap_mcty, - -1, -1, -1 }, - { 0, &dmap_apro, - -1, -1, -1 }, - { 0, &dmap_avdb, - -1, -1, -1 }, - { 0, &dmap_abro, - -1, -1, -1 }, - { 0, &dmap_abal, - -1, -1, -1 }, - { 0, &dmap_abar, - -1, -1, -1 }, - { 0, &dmap_abcp, - -1, -1, -1 }, - { 0, &dmap_abgn, - -1, -1, -1 }, - { 0, &dmap_adbs, - -1, -1, -1 }, - { 0, &dmap_asal, - dbmfi_offsetof(album), -1, -1 }, - { 0, &dmap_asai, - dbmfi_offsetof(songalbumid), -1, -1 }, - { 0, &dmap_asaa, - dbmfi_offsetof(album_artist), -1, dbgri_offsetof(songalbumartist) }, - { 0, &dmap_asar, - dbmfi_offsetof(artist), -1, -1 }, - { 0, &dmap_asbt, - dbmfi_offsetof(bpm), -1, -1 }, - { 0, &dmap_asbr, - dbmfi_offsetof(bitrate), -1, -1 }, - { 0, &dmap_ascm, - dbmfi_offsetof(comment), -1, -1 }, - { 0, &dmap_asco, - dbmfi_offsetof(compilation), -1, -1 }, - { 0, &dmap_ascp, - dbmfi_offsetof(composer), -1, -1 }, - { 0, &dmap_asda, - dbmfi_offsetof(time_added), -1, -1 }, - { 0, &dmap_asdm, - dbmfi_offsetof(time_modified), -1, -1 }, - { 0, &dmap_asdc, - dbmfi_offsetof(total_discs), -1, -1 }, - { 0, &dmap_asdn, - dbmfi_offsetof(disc), -1, -1 }, - { 0, &dmap_asdb, - dbmfi_offsetof(disabled), -1, -1 }, - { 0, &dmap_aseq, - -1, -1, -1 }, - { 0, &dmap_asfm, - dbmfi_offsetof(type), -1, -1 }, - { 0, &dmap_asgn, - dbmfi_offsetof(genre), -1, -1 }, - { 0, &dmap_asdt, - dbmfi_offsetof(description), -1, -1 }, - { 0, &dmap_asrv, - -1, -1, -1 }, - { 0, &dmap_assr, - dbmfi_offsetof(samplerate), -1, -1 }, - { 0, &dmap_assz, - dbmfi_offsetof(file_size), -1, -1 }, - { 0, &dmap_asst, - -1, -1, -1 }, - { 0, &dmap_assp, - -1, -1, -1 }, - { 0, &dmap_astm, - dbmfi_offsetof(song_length), -1, -1 }, - { 0, &dmap_astc, - dbmfi_offsetof(total_tracks), -1, -1 }, - { 0, &dmap_astn, - dbmfi_offsetof(track), -1, -1 }, - { 0, &dmap_asur, - dbmfi_offsetof(rating), -1, -1 }, - { 0, &dmap_asyr, - dbmfi_offsetof(year), -1, -1 }, - { 0, &dmap_asdk, - dbmfi_offsetof(data_kind), -1, -1 }, - { 0, &dmap_asul, - dbmfi_offsetof(url), -1, -1 }, - { 0, &dmap_aply, - -1, -1, -1 }, - { 0, &dmap_abpl, - -1, -1, -1 }, - { 0, &dmap_apso, - -1, -1, -1 }, - { 0, &dmap_arsv, - -1, -1, -1 }, - { 0, &dmap_arif, - -1, -1, -1 }, - { 0, &dmap_aeNV, - -1, -1, -1 }, - { 0, &dmap_aeSP, - -1, -1, -1 }, - { 0, &dmap_aePS, - -1, -1, -1 }, - - /* iTunes 4.5+ */ - { 0, &dmap_ascd, - dbmfi_offsetof(codectype), -1, -1 }, - { 0, &dmap_ascs, - -1, -1, -1 }, - { 0, &dmap_agrp, - dbmfi_offsetof(grouping), -1, -1 }, - { 0, &dmap_aeSV, - -1, -1, -1 }, - { 0, &dmap_aePI, - -1, -1, -1 }, - { 0, &dmap_aeCI, - -1, -1, -1 }, - { 0, &dmap_aeGI, - -1, -1, -1 }, - { 0, &dmap_aeAI, - -1, -1, -1 }, - { 0, &dmap_aeSI, - -1, -1, -1 }, - { 0, &dmap_aeSF, - -1, -1, -1 }, - - /* iTunes 5.0+ */ - { 0, &dmap_ascr, - dbmfi_offsetof(contentrating), -1, -1 }, -#if 0 - { 0, DMAP_TYPE_BYTE, "f" "\x8d" "ch", "dmap.haschildcontainers", - -1, -1, -1 }, -#endif - - /* iTunes 6.0.2+ */ - { 0, &dmap_aeHV, - dbmfi_offsetof(has_video), -1, -1 }, - - /* iTunes 6.0.4+ */ - { 0, &dmap_msas, - -1, -1, -1 }, - { 0, &dmap_asct, - -1, -1, -1 }, - { 0, &dmap_ascn, - -1, -1, -1 }, - { 0, &dmap_aslc, - -1, -1, -1 }, - { 0, &dmap_asky, - -1, -1, -1 }, - { 0, &dmap_apsm, - -1, -1, -1 }, - { 0, &dmap_aprm, - -1, -1, -1 }, - { 0, &dmap_aePC, - -1, -1, -1 }, - { 0, &dmap_aePP, - -1, -1, -1 }, - { 0, &dmap_aeMK, - dbmfi_offsetof(media_kind), -1, -1 }, - { 0, &dmap_aeMk, - dbmfi_offsetof(media_kind), -1, -1 }, - { 0, &dmap_aeSN, - dbmfi_offsetof(tv_series_name), -1, -1 }, - { 0, &dmap_aeNN, - dbmfi_offsetof(tv_network_name), -1, -1 }, - { 0, &dmap_aeEN, - dbmfi_offsetof(tv_episode_num_str), -1, -1 }, - { 0, &dmap_aeES, - dbmfi_offsetof(tv_episode_sort), -1, -1 }, - { 0, &dmap_aeSU, - dbmfi_offsetof(tv_season_num), -1, -1 }, - - { 0, &dmap_assn, - dbmfi_offsetof(title_sort), -1, -1 }, - { 0, &dmap_assa, - dbmfi_offsetof(artist_sort), -1, -1 }, - { 0, &dmap_assu, - dbmfi_offsetof(album_sort), -1, -1 }, - { 0, &dmap_assc, - dbmfi_offsetof(composer_sort), -1, -1 }, - { 0, &dmap_assl, - dbmfi_offsetof(album_artist_sort), -1, -1 }, - - { 0, NULL, - -1, -1, -1 } - }; +/* gperf static hash, dmap_fields.gperf */ +#include "dmap_fields_hash.c" /* Default meta tags if not provided in the query */ static char *default_meta_plsongs = "dmap.itemkind,dmap.itemid,dmap.itemname,dmap.containeritemid,dmap.parentcontainerid"; static char *default_meta_pl = "dmap.itemid,dmap.itemname,dmap.persistentid,com.apple.itunes.smart-playlist"; static char *default_meta_group = "dmap.itemname,dmap.persistentid,daap.songalbumartist"; -static avl_tree_t *dmap_fields_hash; - /* DAAP session tracking */ static avl_tree_t *daap_sessions; static int next_session_id; @@ -717,36 +297,6 @@ update_fail_cb(struct evhttp_connection *evcon, void *arg) /* DMAP fields helpers */ -static int -dmap_field_map_compare(const void *aa, const void *bb) -{ - struct dmap_field_map *a = (struct dmap_field_map *)aa; - struct dmap_field_map *b = (struct dmap_field_map *)bb; - - if (a->hash < b->hash) - return -1; - - if (a->hash > b->hash) - return 1; - - return 0; -} - -static struct dmap_field_map * -dmap_find_field(uint32_t hash) -{ - struct dmap_field_map dfm; - avl_node_t *node; - - dfm.hash = hash; - - node = avl_search(dmap_fields_hash, &dfm); - if (!node) - return NULL; - - return (struct dmap_field_map *)node->item; -} - static void dmap_add_field(struct evbuffer *evbuf, const struct dmap_field *df, char *strval, int32_t intval) { @@ -1118,25 +668,24 @@ get_query_params(struct evkeyvalq *query, int *sort_headers, struct query_params } } -static void -parse_meta(struct evhttp_request *req, char *tag, const char *param, uint32_t **out_meta, int *out_nmeta) +static int +parse_meta(struct evhttp_request *req, char *tag, const char *param, const struct dmap_field ***out_meta) { + const struct dmap_field **meta; char *ptr; - char *meta; + char *field; char *metastr; - uint32_t *hashes; + int nmeta; int i; - *out_nmeta = -1; - metastr = strdup(param); if (!metastr) { DPRINTF(E_LOG, L_DAAP, "Could not duplicate meta parameter; out of memory\n"); dmap_send_error(req, tag, "Out of memory"); - return; + return -1; } nmeta = 1; @@ -1146,34 +695,44 @@ parse_meta(struct evhttp_request *req, char *tag, const char *param, uint32_t ** DPRINTF(E_DBG, L_DAAP, "Asking for %d meta tags\n", nmeta); - hashes = (uint32_t *)malloc((nmeta + 1) * sizeof(uint32_t)); - if (!hashes) + meta = (const struct dmap_field **)malloc(nmeta * sizeof(const struct dmap_field *)); + if (!meta) { DPRINTF(E_LOG, L_DAAP, "Could not allocate meta array; out of memory\n"); dmap_send_error(req, tag, "Out of memory"); - free(metastr); - return; + nmeta = -1; + goto out; } - memset(hashes, 0, (nmeta + 1) * sizeof(uint32_t)); + memset(meta, 0, nmeta * sizeof(struct dmap_field *)); - meta = strtok_r(metastr, ",", &ptr); + field = strtok_r(metastr, ",", &ptr); for (i = 0; i < nmeta; i++) { - hashes[i] = djb_hash(meta, strlen(meta)); + meta[i] = dmap_find_field(field, strlen(field)); - meta = strtok_r(NULL, ",", &ptr); - if (!meta) + if (!meta[i]) + { + DPRINTF(E_WARN, L_DAAP, "Could not find requested meta field '%s'\n", field); + + i--; + nmeta--; + } + + field = strtok_r(NULL, ",", &ptr); + if (!field) break; } DPRINTF(E_DBG, L_DAAP, "Found %d meta tags\n", nmeta); - *out_nmeta = nmeta; - *out_meta = hashes; + *out_meta = meta; + out: free(metastr); + + return nmeta; } @@ -1252,14 +811,13 @@ daap_reply_server_info(struct evhttp_request *req, struct evbuffer *evbuf, char static void daap_reply_content_codes(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) { - const struct dmap_field *df; int i; int len; int ret; len = 12; - for (i = 0; dmap_fields[i].field; i++) - len += 8 + 12 + 10 + 8 + strlen(dmap_fields[i].field->desc); + for (i = 0; i < (sizeof(dmap_fields) / sizeof(dmap_fields[0])); i++) + len += 8 + 12 + 10 + 8 + strlen(dmap_fields[i].desc); ret = evbuffer_expand(evbuf, len + 8); if (ret < 0) @@ -1273,16 +831,14 @@ daap_reply_content_codes(struct evhttp_request *req, struct evbuffer *evbuf, cha dmap_add_container(evbuf, "mccr", len); dmap_add_int(evbuf, "mstt", 200); - for (i = 0; dmap_fields[i].field; i++) + for (i = 0; i < (sizeof(dmap_fields) / sizeof(dmap_fields[0])); i++) { - df = dmap_fields[i].field; - - len = 12 + 10 + 8 + strlen(df->desc); + len = 12 + 10 + 8 + strlen(dmap_fields[i].desc); dmap_add_container(evbuf, "mdcl", len); - dmap_add_string(evbuf, "mcnm", df->tag); /* 12 */ - dmap_add_string(evbuf, "mcna", df->desc); /* 8 + strlen(desc) */ - dmap_add_short(evbuf, "mcty", df->type); /* 10 */ + dmap_add_string(evbuf, "mcnm", dmap_fields[i].tag); /* 12 */ + dmap_add_string(evbuf, "mcna", dmap_fields[i].desc); /* 8 + strlen(desc) */ + dmap_add_short(evbuf, "mcty", dmap_fields[i].type); /* 10 */ } httpd_send_reply(req, HTTP_OK, "OK", evbuf); @@ -1507,13 +1063,14 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, struct db_media_file_info dbmfi; struct evbuffer *song; struct evbuffer *songlist; - struct dmap_field_map *dfm; + const struct dmap_field_map *dfm; + const struct dmap_field *df; + const struct dmap_field **meta; struct sort_ctx *sctx; const char *param; char *tag; char **strval; char *ptr; - uint32_t *meta; int nmeta; int sort_headers; int nsongs; @@ -1589,7 +1146,7 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, if (param) { - parse_meta(req, tag, param, &meta, &nmeta); + nmeta = parse_meta(req, tag, param, &meta); if (nmeta < 0) { DPRINTF(E_LOG, L_DAAP, "Failed to parse meta parameter in DAAP query\n"); @@ -1660,22 +1217,18 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, if (i == nmeta) break; - dfm = dmap_find_field(meta[i]); - - if (!dfm) - { - DPRINTF(E_WARN, L_DAAP, "Could not find requested meta field (%d)\n", i + 1); - continue; - } + df = meta[i]; + dfm = df->dfm; } /* No specific meta tags requested, send out everything */ else { /* End of list */ - if (!dmap_fields[i].field) + if (i == (sizeof(dmap_fields) / sizeof(dmap_fields[0]))) break; - dfm = &dmap_fields[i]; + df = &dmap_fields[i]; + dfm = dmap_fields[i].dfm; } /* Not in struct media_file_info */ @@ -1683,20 +1236,20 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, continue; /* Will be prepended to the list */ - if (dfm->field == &dmap_mikd) + if (dfm == &dfm_dmap_mikd) { /* item kind */ want_mikd = 1; continue; } - else if (dfm->field == &dmap_asdk) + else if (dfm == &dfm_dmap_asdk) { /* data kind */ want_asdk = 1; continue; } - DPRINTF(E_DBG, L_DAAP, "Investigating %s\n", dfm->field->desc); + DPRINTF(E_DBG, L_DAAP, "Investigating %s\n", df->desc); strval = (char **) ((char *)&dbmfi + dfm->mfi_offset); @@ -1704,9 +1257,9 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, continue; /* Here's one exception ... codectype (ascd) is actually an integer */ - if (dfm->field == &dmap_ascd) + if (dfm == &dfm_dmap_ascd) { - dmap_add_literal(song, dfm->field->tag, *strval, 4); + dmap_add_literal(song, df->tag, *strval, 4); continue; } @@ -1743,9 +1296,9 @@ daap_reply_songlist_generic(struct evhttp_request *req, struct evbuffer *evbuf, } } - dmap_add_field(song, dfm->field, *strval, val); + dmap_add_field(song, df, *strval, val); - DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", dfm->field->desc, *strval); + DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", df->desc, *strval); } /* Always include sort tags */ @@ -1935,10 +1488,11 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** struct daap_session *s; struct evbuffer *playlistlist; struct evbuffer *playlist; - struct dmap_field_map *dfm; + const struct dmap_field_map *dfm; + const struct dmap_field *df; + const struct dmap_field **meta; const char *param; char **strval; - uint32_t *meta; int nmeta; int npls; int32_t val; @@ -2004,7 +1558,7 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** param = default_meta_pl; } - parse_meta(req, "aply", param, &meta, &nmeta); + nmeta = parse_meta(req, "aply", param, &meta); if (nmeta < 0) { DPRINTF(E_LOG, L_DAAP, "Failed to parse meta parameter in DAAP query\n"); @@ -2032,19 +1586,15 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** for (i = 0; i < nmeta; i++) { - dfm = dmap_find_field(meta[i]); - if (!dfm) - { - DPRINTF(E_WARN, L_DAAP, "Could not find requested meta field (%d)\n", i + 1); - continue; - } + df = meta[i]; + dfm = df->dfm; /* dmap.itemcount - always added */ - if (dfm->field == &dmap_mimc) + if (dfm == &dfm_dmap_mimc) continue; /* com.apple.itunes.smart-playlist - type = 1 AND id != 1 */ - if (dfm->field == &dmap_aeSP) + if (dfm == &dfm_dmap_aeSP) { val = 0; ret = safe_atoi32(dbpli.type, &val); @@ -2075,9 +1625,9 @@ daap_reply_playlists(struct evhttp_request *req, struct evbuffer *evbuf, char ** if (!(*strval) || (**strval == '\0')) continue; - dmap_add_field(playlist, dfm->field, *strval, 0); + dmap_add_field(playlist, df, *strval, 0); - DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", dfm->field->desc, *strval); + DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", df->desc, *strval); } /* Item count (mimc) */ @@ -2174,11 +1724,12 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri struct daap_session *s; struct evbuffer *group; struct evbuffer *grouplist; - struct dmap_field_map *dfm; + const struct dmap_field_map *dfm; + const struct dmap_field *df; + const struct dmap_field **meta; struct sort_ctx *sctx; const char *param; char **strval; - uint32_t *meta; int nmeta; int sort_headers; int ngrp; @@ -2249,7 +1800,7 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri param = default_meta_group; } - parse_meta(req, tag, param, &meta, &nmeta); + nmeta = parse_meta(req, tag, param, &meta); if (nmeta < 0) { DPRINTF(E_LOG, L_DAAP, "Failed to parse meta parameter in DAAP query\n"); @@ -2294,15 +1845,11 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri for (i = 0; i < nmeta; i++) { - dfm = dmap_find_field(meta[i]); - if (!dfm) - { - DPRINTF(E_WARN, L_DAAP, "Could not find requested meta field (%d)\n", i + 1); - continue; - } + df = meta[i]; + dfm = df->dfm; /* dmap.itemcount - always added */ - if (dfm->field == &dmap_mimc) + if (dfm == &dfm_dmap_mimc) continue; /* Not in struct group_info */ @@ -2314,9 +1861,9 @@ daap_reply_groups(struct evhttp_request *req, struct evbuffer *evbuf, char **uri if (!(*strval) || (**strval == '\0')) continue; - dmap_add_field(group, dfm->field, *strval, 0); + dmap_add_field(group, df, *strval, 0); - DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", dfm->field->desc, *strval); + DPRINTF(E_DBG, L_DAAP, "Done with meta tag %s (%s)\n", df->desc, *strval); } if (sort_headers) @@ -2780,16 +2327,16 @@ daap_fix_request_uri(struct evhttp_request *req, char *uri) #ifdef DMAP_TEST -static const struct dmap_field dmap_TEST = { "TEST", "test.container", DMAP_TYPE_LIST }; -static const struct dmap_field dmap_TST1 = { "TST1", "test.ubyte", DMAP_TYPE_UBYTE }; -static const struct dmap_field dmap_TST2 = { "TST2", "test.byte", DMAP_TYPE_BYTE }; -static const struct dmap_field dmap_TST3 = { "TST3", "test.ushort", DMAP_TYPE_USHORT }; -static const struct dmap_field dmap_TST4 = { "TST4", "test.short", DMAP_TYPE_SHORT }; -static const struct dmap_field dmap_TST5 = { "TST5", "test.uint", DMAP_TYPE_UINT }; -static const struct dmap_field dmap_TST6 = { "TST6", "test.int", DMAP_TYPE_INT }; -static const struct dmap_field dmap_TST7 = { "TST7", "test.ulong", DMAP_TYPE_ULONG }; -static const struct dmap_field dmap_TST8 = { "TST8", "test.long", DMAP_TYPE_LONG }; -static const struct dmap_field dmap_TST9 = { "TST9", "test.string", DMAP_TYPE_STRING }; +static const struct dmap_field dmap_TEST = { "test.container", "TEST", NULL, DMAP_TYPE_LIST }; +static const struct dmap_field dmap_TST1 = { "test.ubyte", "TST1", NULL, DMAP_TYPE_UBYTE }; +static const struct dmap_field dmap_TST2 = { "test.byte", "TST2", NULL, DMAP_TYPE_BYTE }; +static const struct dmap_field dmap_TST3 = { "test.ushort", "TST3", NULL, DMAP_TYPE_USHORT }; +static const struct dmap_field dmap_TST4 = { "test.short", "TST4", NULL, DMAP_TYPE_SHORT }; +static const struct dmap_field dmap_TST5 = { "test.uint", "TST5", NULL, DMAP_TYPE_UINT }; +static const struct dmap_field dmap_TST6 = { "test.int", "TST6", NULL, DMAP_TYPE_INT }; +static const struct dmap_field dmap_TST7 = { "test.ulong", "TST7", NULL, DMAP_TYPE_ULONG }; +static const struct dmap_field dmap_TST8 = { "test.long", "TST8", NULL, DMAP_TYPE_LONG }; +static const struct dmap_field dmap_TST9 = { "test.string", "TST9", NULL, DMAP_TYPE_STRING }; static void daap_reply_dmap_test(struct evhttp_request *req, struct evbuffer *evbuf, char **uri, struct evkeyvalq *query) @@ -3166,8 +2713,6 @@ int daap_init(void) { char buf[64]; - avl_node_t *node; - struct dmap_field_map *dfm; int i; int ret; @@ -3194,44 +2739,8 @@ daap_init(void) goto daap_avl_alloc_fail; } - dmap_fields_hash = avl_alloc_tree(dmap_field_map_compare, NULL); - if (!dmap_fields_hash) - { - DPRINTF(E_FATAL, L_DAAP, "DAAP init could not allocate DMAP fields AVL tree\n"); - - goto dmap_avl_alloc_fail; - } - - for (i = 0; dmap_fields[i].field; i++) - { - dmap_fields[i].hash = djb_hash(dmap_fields[i].field->desc, strlen(dmap_fields[i].field->desc)); - - node = avl_insert(dmap_fields_hash, &dmap_fields[i]); - if (!node) - { - if (errno != EEXIST) - DPRINTF(E_FATAL, L_DAAP, "DAAP init failed; AVL insert error: %s\n", strerror(errno)); - else - { - node = avl_search(dmap_fields_hash, &dmap_fields[i]); - dfm = node->item; - - DPRINTF(E_FATAL, L_DAAP, "DAAP init failed; WARNING: duplicate hash key\n"); - DPRINTF(E_FATAL, L_DAAP, "Hash %x, string %s\n", dmap_fields[i].hash, dmap_fields[i].field->desc); - - DPRINTF(E_FATAL, L_DAAP, "Hash %x, string %s\n", dfm->hash, dfm->field->desc); - } - - goto dmap_avl_insert_fail; - } - } - return 0; - dmap_avl_insert_fail: - avl_free_tree(dmap_fields_hash); - dmap_avl_alloc_fail: - avl_free_tree(daap_sessions); daap_avl_alloc_fail: for (i = 0; daap_handlers[i].handler; i++) regfree(&daap_handlers[i].preg); @@ -3249,7 +2758,6 @@ daap_deinit(void) regfree(&daap_handlers[i].preg); avl_free_tree(daap_sessions); - avl_free_tree(dmap_fields_hash); for (ur = update_requests; update_requests; ur = update_requests) {