diff --git a/src/daap_query.gperf b/src/daap_query.gperf index 5c80221b..54f5673b 100644 --- a/src/daap_query.gperf +++ b/src/daap_query.gperf @@ -26,6 +26,7 @@ struct dmap_query_field_map; "daap.songdataurl", "f.url", 0 "daap.songdateadded", "f.time_added", 1 "daap.songdatemodified", "f.time_modified", 1 +"daap.songdatereleased", "f.date_released", 1 "daap.songdescription", "f.description", 0 "daap.songdisccount", "f.total_discs", 1 "daap.songdiscnumber", "f.disc", 1 diff --git a/src/db.c b/src/db.c index c362f4d9..2c647d39 100644 --- a/src/db.c +++ b/src/db.c @@ -2538,7 +2538,7 @@ db_file_add(struct media_file_info *mfi) " media_kind, tv_series_name, tv_episode_num_str, tv_network_name, tv_episode_sort, tv_season_num, " \ " songartistid, songalbumid, " \ " title_sort, artist_sort, album_sort, composer_sort, album_artist_sort, virtual_path," \ - " directory_id) " \ + " directory_id, date_released) " \ " VALUES (NULL, '%q', '%q', TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), %Q, TRIM(%Q)," \ " TRIM(%Q), TRIM(%Q), TRIM(%Q), %Q, %d, %d, %d, %" PRIi64 ", %d, %d," \ " %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d," \ @@ -2546,7 +2546,7 @@ db_file_add(struct media_file_info *mfi) " %Q, %d, %d, %d, %d, TRIM(%Q)," \ " %d, TRIM(%Q), TRIM(%Q), TRIM(%Q), %d, %d," \ " daap_songalbumid(LOWER(TRIM(%Q)), ''), daap_songalbumid(LOWER(TRIM(%Q)), LOWER(TRIM(%Q))), " \ - " TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), %d);" + " TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), TRIM(%Q), %d, %d);" char *query; char *errmsg; @@ -2581,7 +2581,7 @@ db_file_add(struct media_file_info *mfi) mfi->media_kind, mfi->tv_series_name, mfi->tv_episode_num_str, mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num, mfi->album_artist, mfi->album_artist, mfi->album, mfi->title_sort, mfi->artist_sort, mfi->album_sort, - mfi->composer_sort, mfi->album_artist_sort, mfi->virtual_path, mfi->directory_id); + mfi->composer_sort, mfi->album_artist_sort, mfi->virtual_path, mfi->directory_id, mfi->date_released); if (!query) { @@ -2626,7 +2626,7 @@ db_file_update(struct media_file_info *mfi) " tv_network_name = TRIM(%Q), tv_episode_sort = %d, tv_season_num = %d," \ " songartistid = daap_songalbumid(LOWER(TRIM(%Q)), ''), songalbumid = daap_songalbumid(LOWER(TRIM(%Q)), LOWER(TRIM(%Q)))," \ " title_sort = TRIM(%Q), artist_sort = TRIM(%Q), album_sort = TRIM(%Q), composer_sort = TRIM(%Q), album_artist_sort = TRIM(%Q)," \ - " virtual_path = TRIM(%Q), directory_id = %d" \ + " virtual_path = TRIM(%Q), directory_id = %d, date_released = %d" \ " WHERE id = %d;" char *query; @@ -2658,7 +2658,8 @@ db_file_update(struct media_file_info *mfi) mfi->tv_network_name, mfi->tv_episode_sort, mfi->tv_season_num, mfi->album_artist, mfi->album_artist, mfi->album, mfi->title_sort, mfi->artist_sort, mfi->album_sort, - mfi->composer_sort, mfi->album_artist_sort, mfi->virtual_path, mfi->directory_id, + mfi->composer_sort, mfi->album_artist_sort, + mfi->virtual_path, mfi->directory_id, mfi->date_released, mfi->id); if (!query) diff --git a/src/dmap_fields.gperf b/src/dmap_fields.gperf index c3017acd..7f0d87e1 100644 --- a/src/dmap_fields.gperf +++ b/src/dmap_fields.gperf @@ -67,34 +67,36 @@ static const struct dmap_field_map dfm_dmap_asaa = { dbmfi_offsetof(album_artist static const struct dmap_field_map dfm_dmap_asac = { -1, -1, -1 }; static const struct dmap_field_map dfm_dmap_asar = { dbmfi_offsetof(artist), -1, -1 }; static const struct dmap_field_map dfm_dmap_asri = { dbmfi_offsetof(songartistid), -1, dbgri_offsetof(songartistid) }; -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_asbt = { dbmfi_offsetof(bpm), -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_asdc = { dbmfi_offsetof(total_discs), -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_asdn = { dbmfi_offsetof(disc), -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_asdr = { dbmfi_offsetof(date_released), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asdt = { dbmfi_offsetof(description), -1, -1 }; static const struct dmap_field_map dfm_dmap_ased = { -1, -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_ashp = { dbmfi_offsetof(play_count), -1, -1 }; static const struct dmap_field_map dfm_dmap_aspc = { dbmfi_offsetof(play_count), -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_assr = { dbmfi_offsetof(samplerate), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asst = { -1, -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_asrv = { -1, -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_astm = { dbmfi_offsetof(song_length), -1, -1 }; static const struct dmap_field_map dfm_dmap_astn = { dbmfi_offsetof(track), -1, -1 }; +static const struct dmap_field_map dfm_dmap_asul = { dbmfi_offsetof(url), -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 }; @@ -198,11 +200,13 @@ struct dmap_field; "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.songdatereleased", "asdr", &dfm_dmap_asdr, DMAP_TYPE_DATE "daap.songdescription", "asdt", &dfm_dmap_asdt, DMAP_TYPE_STRING "daap.songextradata", "ased", &dfm_dmap_ased, DMAP_TYPE_USHORT "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.songhasbeenplayed", "ashp", &dfm_dmap_ashp, DMAP_TYPE_UBYTE "daap.songkeywords", "asky", &dfm_dmap_asky, DMAP_TYPE_STRING "daap.songlongcontentdescription", "aslc", &dfm_dmap_aslc, DMAP_TYPE_STRING "daap.songuserplaycount", "aspc", &dfm_dmap_aspc, DMAP_TYPE_UINT @@ -296,9 +300,7 @@ struct dmap_field; "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.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 diff --git a/src/filescanner_ffmpeg.c b/src/filescanner_ffmpeg.c index 9cb83448..1b7cf7e5 100644 --- a/src/filescanner_ffmpeg.c +++ b/src/filescanner_ffmpeg.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -86,6 +87,26 @@ parse_disc(struct media_file_info *mfi, char *disc_string) return parse_slash_separated_ints(disc_string, disc, total_discs); } +static int +parse_date(struct media_file_info *mfi, char *date_string) +{ + struct tm tm; + + memset(&tm, 0, sizeof(struct tm)); + + if ( strptime(date_string, "%FT%T%z", &tm) // ISO 8601, %F=%Y-%m-%d, %T=%H:%M:%S + || strptime(date_string, "%F %T", &tm) + || strptime(date_string, "%F %H:%M", &tm) + || strptime(date_string, "%F", &tm) + || strptime(date_string, "%Y", &tm) + ) + mfi->date_released = (uint32_t)mktime(&tm); + else + return 0; + + return 1; +} + /* Lookup is case-insensitive, first occurrence takes precedence */ static const struct metadata_map md_map_generic[] = { @@ -104,7 +125,7 @@ static const struct metadata_map md_map_generic[] = { "track", 1, mfi_offsetof(track), parse_track }, { "disc", 1, mfi_offsetof(disc), parse_disc }, { "year", 1, mfi_offsetof(year), NULL }, - { "date", 1, mfi_offsetof(year), NULL }, + { "date", 1, mfi_offsetof(date_released), parse_date }, { "title-sort", 0, mfi_offsetof(title_sort), NULL }, { "artist-sort", 0, mfi_offsetof(artist_sort), NULL }, { "album-sort", 0, mfi_offsetof(album_sort), NULL }, @@ -177,7 +198,9 @@ static const struct metadata_map md_map_id3[] = { "TPOS", 1, mfi_offsetof(disc), parse_disc }, /* ID3v2.3 */ { "TYE", 1, mfi_offsetof(year), NULL }, /* ID3v2.2 */ { "TYER", 1, mfi_offsetof(year), NULL }, /* ID3v2.3 */ - { "TDRC", 1, mfi_offsetof(year), NULL }, /* ID3v2.4 */ + { "TDA", 1, mfi_offsetof(date_released), parse_date }, /* ID3v2.2 */ + { "TDAT", 1, mfi_offsetof(date_released), parse_date }, /* ID3v2.3 */ + { "TDRL", 1, mfi_offsetof(date_released), parse_date }, /* ID3v2.4 */ { "TSOA", 0, mfi_offsetof(album_sort), NULL }, /* ID3v2.4 */ { "XSOA", 0, mfi_offsetof(album_sort), NULL }, /* ID3v2.3 */ { "TSOP", 0, mfi_offsetof(artist_sort), NULL }, /* ID3v2.4 */