feat(subsonic): expose replaygain tags
This commit is contained in:
@@ -67,7 +67,7 @@ password can then be changed from the web interface
|
||||
| `GONIC_JUKEBOX_ENABLED` | `-jukebox-enabled` | **optional** whether the subsonic [jukebox api](https://airsonic.github.io/docs/jukebox/) should be enabled |
|
||||
| `GONIC_JUKEBOX_MPV_EXTRA_ARGS` | `-jukebox-mpv-extra-args` | **optional** extra command line arguments to pass to the jukebox mpv daemon |
|
||||
| `GONIC_PODCAST_PURGE_AGE` | `-podcast-purge-age` | **optional** age (in days) to purge podcast episodes if not accessed |
|
||||
| `GONIC_EXCLUDE_PATTERN` | `-exclude-pattern` | **optional** files matching this regex pattern will not be imported. Example : <code>@eaDir\|[aA]rtwork\|[cC]overs\|[sS]cans\|[sS]pectrals</code> |
|
||||
| `GONIC_EXCLUDE_PATTERN` | `-exclude-pattern` | **optional** files matching this regex pattern will not be imported. eg <code>@eaDir\|[aA]rtwork\|[cC]overs\|[sS]cans\|[sS]pectrals</code> |
|
||||
| `GONIC_MULTI_VALUE_GENRE` | `-multi-value-genre` | **optional** setting for multi-valued genre tags when scanning ([see more](#multi-valued-tags-v016)) |
|
||||
| `GONIC_MULTI_VALUE_ARTIST` | `-multi-value-artist` | **optional** setting for multi-valued artist tags when scanning ([see more](#multi-valued-tags-v016)) |
|
||||
| `GONIC_MULTI_VALUE_ALBUM_ARTIST` | `-multi-value-album-artist` | **optional** setting for multi-valued album artist tags when scanning ([see more](#multi-valued-tags-v016)) |
|
||||
@@ -97,7 +97,7 @@ the available modes are:
|
||||
|
||||
gonic supports multiple music folders. this can be handy if you have your music separated by albums, compilations, singles. or maybe 70s, 80s, 90s. whatever.
|
||||
|
||||
on top of that - if you don't decide your folder names, or simply do not want the same name in your subsonic client,
|
||||
on top of that - if you don't decide your folder names, or simply do not want the same name in your subsonic client,
|
||||
gonic can parse aliases for the folder names with the optional `ALIAS->PATH` syntax
|
||||
|
||||
if you're running gonic with the command line, stack the `-music-path` arg
|
||||
|
||||
12
db/db.go
12
db/db.go
@@ -235,9 +235,15 @@ type Track struct {
|
||||
TagTrackNumber int `sql:"default: null"`
|
||||
TagDiscNumber int `sql:"default: null"`
|
||||
TagBrainzID string `sql:"default: null"`
|
||||
TrackStar *TrackStar
|
||||
TrackRating *TrackRating
|
||||
AverageRating float64 `sql:"default: null"`
|
||||
|
||||
ReplayGainTrackGain float32
|
||||
ReplayGainTrackPeak float32
|
||||
ReplayGainAlbumGain float32
|
||||
ReplayGainAlbumPeak float32
|
||||
|
||||
TrackStar *TrackStar
|
||||
TrackRating *TrackRating
|
||||
AverageRating float64 `sql:"default: null"`
|
||||
}
|
||||
|
||||
func (t *Track) AudioLength() int { return t.Length }
|
||||
|
||||
@@ -72,6 +72,7 @@ func (db *DB) Migrate(ctx MigrationContext) error {
|
||||
construct(ctx, "202311072309", migrateAlbumInfo),
|
||||
construct(ctx, "202311082304", migrateTemporaryDisplayAlbumArtist),
|
||||
construct(ctx, "202312110003", migrateAddExtraIndexes),
|
||||
construct(ctx, "202405301140", migrateAddReplayGainFields),
|
||||
}
|
||||
|
||||
return gormigrate.
|
||||
@@ -813,3 +814,7 @@ func migrateAddExtraIndexes(tx *gorm.DB, _ MigrationContext) error {
|
||||
CREATE INDEX idx_artist_appearances_album_id ON "artist_appearances" (album_id);
|
||||
`).Error
|
||||
}
|
||||
|
||||
func migrateAddReplayGainFields(tx *gorm.DB, _ MigrationContext) error {
|
||||
return tx.AutoMigrate(Track{}).Error
|
||||
}
|
||||
|
||||
@@ -362,8 +362,14 @@ func (i *TagInfo) Genres() []string { return []string{i.RawGenre} }
|
||||
func (i *TagInfo) TrackNumber() int { return 1 }
|
||||
func (i *TagInfo) DiscNumber() int { return 1 }
|
||||
func (i *TagInfo) Year() int { return 2021 }
|
||||
func (i *TagInfo) Length() int { return firstInt(100, i.RawLength) }
|
||||
func (i *TagInfo) Bitrate() int { return firstInt(100, i.RawBitrate) }
|
||||
|
||||
func (i *TagInfo) ReplayGainTrackGain() float32 { return 0 }
|
||||
func (i *TagInfo) ReplayGainTrackPeak() float32 { return 0 }
|
||||
func (i *TagInfo) ReplayGainAlbumGain() float32 { return 0 }
|
||||
func (i *TagInfo) ReplayGainAlbumPeak() float32 { return 0 }
|
||||
|
||||
func (i *TagInfo) Length() int { return firstInt(100, i.RawLength) }
|
||||
func (i *TagInfo) Bitrate() int { return firstInt(100, i.RawBitrate) }
|
||||
|
||||
var _ tagcommon.Reader = (*tagReader)(nil)
|
||||
|
||||
|
||||
@@ -469,8 +469,14 @@ func populateTrack(tx *db.DB, album *db.Album, track *db.Track, trags tagcommon.
|
||||
track.TagDiscNumber = trags.DiscNumber()
|
||||
track.TagBrainzID = trags.BrainzID()
|
||||
|
||||
track.Length = trags.Length() // these two should be calculated
|
||||
track.Bitrate = trags.Bitrate() // ...from the file instead of tags
|
||||
track.ReplayGainTrackGain = trags.ReplayGainTrackGain()
|
||||
track.ReplayGainTrackPeak = trags.ReplayGainTrackPeak()
|
||||
track.ReplayGainAlbumGain = trags.ReplayGainAlbumGain()
|
||||
track.ReplayGainAlbumPeak = trags.ReplayGainAlbumPeak()
|
||||
|
||||
// these two are calculated from the file instead of tags
|
||||
track.Length = trags.Length()
|
||||
track.Bitrate = trags.Bitrate()
|
||||
|
||||
if err := tx.Save(&track).Error; err != nil {
|
||||
return fmt.Errorf("saving track: %w", err)
|
||||
|
||||
@@ -102,6 +102,14 @@ func NewTCTrackByFolder(t *db.Track, parent *db.Album) *TrackChild {
|
||||
for _, a := range t.Artists {
|
||||
trCh.Artists = append(trCh.Artists, &ArtistRef{ID: a.SID(), Name: a.Name})
|
||||
}
|
||||
if t.ReplayGainTrackGain != 0 || t.ReplayGainAlbumGain != 0 {
|
||||
trCh.ReplayGain = &ReplayGain{
|
||||
TrackGain: t.ReplayGainTrackGain,
|
||||
TrackPeak: t.ReplayGainTrackPeak,
|
||||
AlbumGain: t.ReplayGainAlbumGain,
|
||||
AlbumPeak: t.ReplayGainAlbumPeak,
|
||||
}
|
||||
}
|
||||
return trCh
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,14 @@ func NewTrackByTags(t *db.Track, album *db.Album) *TrackChild {
|
||||
for _, a := range album.Artists {
|
||||
ret.AlbumArtists = append(ret.AlbumArtists, &ArtistRef{ID: a.SID(), Name: a.Name})
|
||||
}
|
||||
if t.ReplayGainTrackGain != 0 || t.ReplayGainAlbumGain != 0 {
|
||||
ret.ReplayGain = &ReplayGain{
|
||||
TrackGain: t.ReplayGainTrackGain,
|
||||
TrackPeak: t.ReplayGainTrackPeak,
|
||||
AlbumGain: t.ReplayGainAlbumGain,
|
||||
AlbumPeak: t.ReplayGainAlbumPeak,
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
@@ -169,6 +169,13 @@ type TranscodeMeta struct {
|
||||
TranscodedSuffix string `xml:"transcodedSuffix,attr,omitempty" json:"transcodedSuffix,omitempty"`
|
||||
}
|
||||
|
||||
type ReplayGain struct {
|
||||
TrackGain float32 `xml:"trackGain,attr" json:"trackGain"`
|
||||
TrackPeak float32 `xml:"trackPeak,attr" json:"trackPeak"`
|
||||
AlbumGain float32 `xml:"albumGain,attr" json:"albumGain"`
|
||||
AlbumPeak float32 `xml:"albumPeak,attr" json:"albumPeak"`
|
||||
}
|
||||
|
||||
// https://opensubsonic.netlify.app/docs/responses/child/
|
||||
type TrackChild struct {
|
||||
ID *specid.ID `xml:"id,attr,omitempty" json:"id,omitempty"`
|
||||
@@ -211,6 +218,8 @@ type TrackChild struct {
|
||||
UserRating int `xml:"userRating,attr,omitempty" json:"userRating,omitempty"`
|
||||
AverageRating string `xml:"averageRating,attr,omitempty" json:"averageRating,omitempty"`
|
||||
|
||||
ReplayGain *ReplayGain `xml:"replayGain" json:"replayGain"`
|
||||
|
||||
TranscodeMeta
|
||||
}
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
"albumList": {
|
||||
"album": [
|
||||
{
|
||||
"id": "al-9",
|
||||
"id": "al-5",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-1",
|
||||
"artist": "artist-0",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"parent": "al-6",
|
||||
"parent": "al-2",
|
||||
"isDir": true,
|
||||
"coverArt": "al-9",
|
||||
"coverArt": "al-5",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
@@ -40,48 +40,16 @@
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-4",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-0",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"parent": "al-2",
|
||||
"isDir": true,
|
||||
"coverArt": "al-4",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-12",
|
||||
"id": "al-13",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-2",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"parent": "al-10",
|
||||
"isDir": true,
|
||||
"coverArt": "al-12",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-5",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-0",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"parent": "al-2",
|
||||
"parent": "al-10",
|
||||
"isDir": true,
|
||||
"coverArt": "al-5",
|
||||
"coverArt": "al-13",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
@@ -103,6 +71,54 @@
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-4",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-0",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"parent": "al-2",
|
||||
"isDir": true,
|
||||
"coverArt": "al-4",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-9",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-1",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"parent": "al-6",
|
||||
"isDir": true,
|
||||
"coverArt": "al-9",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-12",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-2",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"parent": "al-10",
|
||||
"isDir": true,
|
||||
"coverArt": "al-12",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-8",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
@@ -119,22 +135,6 @@
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-13",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artist": "artist-2",
|
||||
"artists": null,
|
||||
"displayArtist": "",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"parent": "al-10",
|
||||
"isDir": true,
|
||||
"coverArt": "al-13",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0
|
||||
},
|
||||
{
|
||||
"id": "al-11",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
|
||||
@@ -24,32 +24,16 @@
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-5",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-1",
|
||||
"artist": "artist-0",
|
||||
"artists": [{ "id": "ar-1", "name": "artist-0" }],
|
||||
"displayArtist": "artist-0",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"coverArt": "al-5",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-8",
|
||||
"id": "al-7",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-2",
|
||||
"artist": "artist-1",
|
||||
"artists": [{ "id": "ar-2", "name": "artist-1" }],
|
||||
"displayArtist": "artist-1",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"coverArt": "al-8",
|
||||
"name": "album-1",
|
||||
"title": "album-0",
|
||||
"album": "album-0",
|
||||
"coverArt": "al-7",
|
||||
"name": "album-0",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
@@ -71,38 +55,6 @@
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-12",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-3",
|
||||
"artist": "artist-2",
|
||||
"artists": [{ "id": "ar-3", "name": "artist-2" }],
|
||||
"displayArtist": "artist-2",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"coverArt": "al-12",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-7",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-2",
|
||||
"artist": "artist-1",
|
||||
"artists": [{ "id": "ar-2", "name": "artist-1" }],
|
||||
"displayArtist": "artist-1",
|
||||
"title": "album-0",
|
||||
"album": "album-0",
|
||||
"coverArt": "al-7",
|
||||
"name": "album-0",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-13",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
@@ -135,6 +87,54 @@
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-12",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-3",
|
||||
"artist": "artist-2",
|
||||
"artists": [{ "id": "ar-3", "name": "artist-2" }],
|
||||
"displayArtist": "artist-2",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"coverArt": "al-12",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-5",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-1",
|
||||
"artist": "artist-0",
|
||||
"artists": [{ "id": "ar-1", "name": "artist-0" }],
|
||||
"displayArtist": "artist-0",
|
||||
"title": "album-2",
|
||||
"album": "album-2",
|
||||
"coverArt": "al-5",
|
||||
"name": "album-2",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-8",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
"artistId": "ar-2",
|
||||
"artist": "artist-1",
|
||||
"artists": [{ "id": "ar-2", "name": "artist-1" }],
|
||||
"displayArtist": "artist-1",
|
||||
"title": "album-1",
|
||||
"album": "album-1",
|
||||
"coverArt": "al-8",
|
||||
"name": "album-1",
|
||||
"songCount": 3,
|
||||
"duration": 300,
|
||||
"playCount": 0,
|
||||
"year": 2021
|
||||
},
|
||||
{
|
||||
"id": "al-9",
|
||||
"created": "2019-11-30T00:00:00Z",
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-2",
|
||||
@@ -75,7 +76,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-3",
|
||||
@@ -102,7 +104,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-2",
|
||||
@@ -58,7 +59,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-3",
|
||||
@@ -83,7 +85,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-0",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-4",
|
||||
@@ -38,7 +39,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-1",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-5",
|
||||
@@ -53,7 +55,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-2",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-2",
|
||||
@@ -63,7 +64,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-3",
|
||||
@@ -92,7 +94,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-4",
|
||||
@@ -121,7 +124,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-5",
|
||||
@@ -150,7 +154,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-6",
|
||||
@@ -179,7 +184,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-7",
|
||||
@@ -208,7 +214,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-8",
|
||||
@@ -237,7 +244,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-9",
|
||||
@@ -266,7 +274,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-10",
|
||||
@@ -295,7 +304,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-11",
|
||||
@@ -324,7 +334,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-12",
|
||||
@@ -353,7 +364,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-13",
|
||||
@@ -382,7 +394,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-14",
|
||||
@@ -411,7 +424,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-15",
|
||||
@@ -440,7 +454,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-16",
|
||||
@@ -469,7 +484,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-17",
|
||||
@@ -498,7 +514,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-18",
|
||||
@@ -527,7 +544,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-19",
|
||||
@@ -556,7 +574,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-20",
|
||||
@@ -585,7 +604,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,7 +20,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-0",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-4",
|
||||
@@ -35,7 +36,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-1",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-5",
|
||||
@@ -50,7 +52,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-2",
|
||||
"title": "album-2",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-7",
|
||||
@@ -65,7 +68,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-6",
|
||||
"title": "album-0",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-8",
|
||||
@@ -80,7 +84,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-6",
|
||||
"title": "album-1",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-9",
|
||||
@@ -95,7 +100,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-6",
|
||||
"title": "album-2",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-11",
|
||||
@@ -110,7 +116,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-10",
|
||||
"title": "album-0",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-12",
|
||||
@@ -125,7 +132,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-10",
|
||||
"title": "album-1",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "al-13",
|
||||
@@ -140,7 +148,8 @@
|
||||
"isVideo": false,
|
||||
"parent": "al-10",
|
||||
"title": "album-2",
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-2",
|
||||
@@ -55,7 +56,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-3",
|
||||
@@ -80,7 +82,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-4",
|
||||
@@ -105,7 +108,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-5",
|
||||
@@ -130,7 +134,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-6",
|
||||
@@ -155,7 +160,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-7",
|
||||
@@ -180,7 +186,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-8",
|
||||
@@ -205,7 +212,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-9",
|
||||
@@ -230,7 +238,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-10",
|
||||
@@ -255,7 +264,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-11",
|
||||
@@ -280,7 +290,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-12",
|
||||
@@ -305,7 +316,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-13",
|
||||
@@ -330,7 +342,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-14",
|
||||
@@ -355,7 +368,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-15",
|
||||
@@ -380,7 +394,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-16",
|
||||
@@ -405,7 +420,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-17",
|
||||
@@ -430,7 +446,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-18",
|
||||
@@ -455,7 +472,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-19",
|
||||
@@ -480,7 +498,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
},
|
||||
{
|
||||
"id": "tr-20",
|
||||
@@ -505,7 +524,8 @@
|
||||
"discNumber": 1,
|
||||
"type": "music",
|
||||
"year": 2021,
|
||||
"musicBrainzId": ""
|
||||
"musicBrainzId": "",
|
||||
"replayGain": null
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -24,9 +24,15 @@ type Info interface {
|
||||
Genres() []string
|
||||
TrackNumber() int
|
||||
DiscNumber() int
|
||||
Year() int
|
||||
|
||||
ReplayGainTrackGain() float32
|
||||
ReplayGainTrackPeak() float32
|
||||
ReplayGainAlbumGain() float32
|
||||
ReplayGainAlbumPeak() float32
|
||||
|
||||
Length() int
|
||||
Bitrate() int
|
||||
Year() int
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -51,8 +51,14 @@ func (i *info) Genres() []string { return find(i.raw, "genres") }
|
||||
func (i *info) TrackNumber() int { return intSep("/", first(find(i.raw, "tracknumber"))) } // eg. 5/12
|
||||
func (i *info) DiscNumber() int { return intSep("/", first(find(i.raw, "discnumber"))) } // eg. 1/2
|
||||
func (i *info) Year() int { return intSep("-", first(find(i.raw, "originaldate", "date", "year"))) } // eg. 2023-12-01
|
||||
func (i *info) Length() int { return i.props.Length }
|
||||
func (i *info) Bitrate() int { return i.props.Bitrate }
|
||||
|
||||
func (i *info) ReplayGainTrackGain() float32 { return dB(first(find(i.raw, "replaygain_track_gain"))) }
|
||||
func (i *info) ReplayGainTrackPeak() float32 { return flt(first(find(i.raw, "replaygain_track_peak"))) }
|
||||
func (i *info) ReplayGainAlbumGain() float32 { return dB(first(find(i.raw, "replaygain_album_gain"))) }
|
||||
func (i *info) ReplayGainAlbumPeak() float32 { return flt(first(find(i.raw, "replaygain_album_peak"))) }
|
||||
|
||||
func (i *info) Length() int { return i.props.Length }
|
||||
func (i *info) Bitrate() int { return i.props.Bitrate }
|
||||
|
||||
func first[T comparable](is []T) T {
|
||||
var z T
|
||||
@@ -83,6 +89,17 @@ func filterStr(ss []string) []string {
|
||||
return r
|
||||
}
|
||||
|
||||
func flt(in string) float32 {
|
||||
f, _ := strconv.ParseFloat(in, 32)
|
||||
return float32(f)
|
||||
}
|
||||
func dB(in string) float32 {
|
||||
in = strings.ToLower(in)
|
||||
in = strings.TrimSuffix(in, " db")
|
||||
in = strings.TrimSuffix(in, "db")
|
||||
return flt(in)
|
||||
}
|
||||
|
||||
func intSep(sep, in string) int {
|
||||
start, _, _ := strings.Cut(in, sep)
|
||||
out, _ := strconv.Atoi(start)
|
||||
|
||||
Reference in New Issue
Block a user