diff --git a/Application/PlaybackEventController.m b/Application/PlaybackEventController.m index f8ff08ee2..ec57ef4ee 100644 --- a/Application/PlaybackEventController.m +++ b/Application/PlaybackEventController.m @@ -118,7 +118,7 @@ typedef NS_ENUM(NSInteger, TrackStatus) { TrackPlaying, TrackPaused, TrackStoppe if ([pe album]) [dict setObject:[pe album] forKey:TrackAlbum]; if ([pe genre]) [dict setObject:[pe genre] forKey:TrackGenre]; if ([pe track]) - [dict setObject:[NSString stringWithFormat:@"%@", [pe track]] forKey:TrackNumber]; + [dict setObject:[pe trackText] forKey:TrackNumber]; if ([pe length]) [dict setObject:[NSNumber numberWithInteger:(NSInteger)([[pe length] doubleValue] * 1000.0)] forKey:TrackLength]; diff --git a/Base.lproj/InfoInspector.xib b/Base.lproj/InfoInspector.xib index ab8226091..6b64594ae 100644 --- a/Base.lproj/InfoInspector.xib +++ b/Base.lproj/InfoInspector.xib @@ -167,8 +167,7 @@ - - + @@ -180,8 +179,7 @@ - - + @@ -191,12 +189,9 @@ - - - - + diff --git a/Base.lproj/MainMenu.xib b/Base.lproj/MainMenu.xib index a58403b39..41d4c4c59 100644 --- a/Base.lproj/MainMenu.xib +++ b/Base.lproj/MainMenu.xib @@ -860,8 +860,8 @@ - + @@ -1052,8 +1052,8 @@ Cog - + diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index 092318d85..90fd50180 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -66,9 +66,6 @@ 17C809E60C3BD487005707C4 /* CoreAudio.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C809E30C3BD46D005707C4 /* CoreAudio.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 17C8F3CF0CBED66C008D969D /* GME.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 17C8F3CD0CBED663008D969D /* GME.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 17D1B1010F63255200694C57 /* InfoWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D1B1000F63255200694C57 /* InfoWindowController.m */; }; - 17D1B1680F632ABB00694C57 /* BlankZeroFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D1B1630F632ABB00694C57 /* BlankZeroFormatter.m */; }; - 17D1B1690F632ABB00694C57 /* IndexFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D1B1650F632ABB00694C57 /* IndexFormatter.m */; }; - 17D1B16A0F632ABB00694C57 /* SecondsFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D1B1670F632ABB00694C57 /* SecondsFormatter.m */; }; 17D1B25D0F633A4F00694C57 /* PreferencePluginController.m in Sources */ = {isa = PBXBuildFile; fileRef = 17D1B25C0F633A4F00694C57 /* PreferencePluginController.m */; }; 17D1B27D0CF8B2830028F5B5 /* cue.icns in Resources */ = {isa = PBXBuildFile; fileRef = 17D1B2760CF8B2830028F5B5 /* cue.icns */; }; 17D1B27E0CF8B2830028F5B5 /* it.icns in Resources */ = {isa = PBXBuildFile; fileRef = 17D1B2770CF8B2830028F5B5 /* it.icns */; }; @@ -120,6 +117,7 @@ 8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 835A8FD327957310005B3C39 /* json.c in Sources */ = {isa = PBXBuildFile; fileRef = 835A8FC627957310005B3C39 /* json.c */; }; 835A8FD6279575B1005B3C39 /* Winamp.q1.json in Resources */ = {isa = PBXBuildFile; fileRef = 835A8FD5279575B1005B3C39 /* Winamp.q1.json */; }; + 835F00BB279BD1CD00055FCF /* SecondsFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 835F00B8279BD1CD00055FCF /* SecondsFormatter.m */; }; 8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; 836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; }; 836F5BF91A357A01002730CC /* sidplay.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8314D6411A354DFF00EEE8E6 /* sidplay.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -852,12 +850,6 @@ 17C8F3C80CBED663008D969D /* GME.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = GME.xcodeproj; path = Plugins/GME/GME.xcodeproj; sourceTree = ""; }; 17D1B0FF0F63255200694C57 /* InfoWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = InfoWindowController.h; path = InfoInspector/InfoWindowController.h; sourceTree = ""; }; 17D1B1000F63255200694C57 /* InfoWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = InfoWindowController.m; path = InfoInspector/InfoWindowController.m; sourceTree = ""; }; - 17D1B1620F632ABB00694C57 /* BlankZeroFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlankZeroFormatter.h; path = Formatters/BlankZeroFormatter.h; sourceTree = ""; }; - 17D1B1630F632ABB00694C57 /* BlankZeroFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BlankZeroFormatter.m; path = Formatters/BlankZeroFormatter.m; sourceTree = ""; }; - 17D1B1640F632ABB00694C57 /* IndexFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IndexFormatter.h; path = Formatters/IndexFormatter.h; sourceTree = ""; }; - 17D1B1650F632ABB00694C57 /* IndexFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IndexFormatter.m; path = Formatters/IndexFormatter.m; sourceTree = ""; }; - 17D1B1660F632ABB00694C57 /* SecondsFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SecondsFormatter.h; path = Formatters/SecondsFormatter.h; sourceTree = ""; }; - 17D1B1670F632ABB00694C57 /* SecondsFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SecondsFormatter.m; path = Formatters/SecondsFormatter.m; sourceTree = ""; }; 17D1B25B0F633A4F00694C57 /* PreferencePluginController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreferencePluginController.h; path = Preferences/PreferencePluginController.h; sourceTree = ""; }; 17D1B25C0F633A4F00694C57 /* PreferencePluginController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PreferencePluginController.m; path = Preferences/PreferencePluginController.m; sourceTree = ""; }; 17D1B2610F633D2C00694C57 /* PreferencePanePlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PreferencePanePlugin.h; path = Preferences/PreferencePanePlugin.h; sourceTree = ""; }; @@ -936,6 +928,8 @@ 835C888B22CC1881001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = en; path = en.lproj/Credits.html; sourceTree = ""; }; 835C888C22CC1882001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 835C888D22CC1882001B4B3F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 835F00B4279BD1CD00055FCF /* SecondsFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SecondsFormatter.h; sourceTree = ""; }; + 835F00B8279BD1CD00055FCF /* SecondsFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SecondsFormatter.m; sourceTree = ""; }; 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = ""; }; 836D28A618086386005B7299 /* MiniModeMenuTitleTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MiniModeMenuTitleTransformer.h; path = Window/MiniModeMenuTitleTransformer.h; sourceTree = ""; }; 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MiniModeMenuTitleTransformer.m; path = Window/MiniModeMenuTitleTransformer.m; sourceTree = ""; }; @@ -1071,7 +1065,7 @@ 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( - 17D1B1230F632A8B00694C57 /* Formatters */, + 835F00B3279BD1CD00055FCF /* Formatters */, 177042960B8BC53600B86321 /* Application */, 17E0D5D20F520E75005B6FED /* Window */, 8E75752A09F31D5A0080F1EE /* Playlist */, @@ -1328,19 +1322,6 @@ name = InfoInspector; sourceTree = ""; }; - 17D1B1230F632A8B00694C57 /* Formatters */ = { - isa = PBXGroup; - children = ( - 17D1B1620F632ABB00694C57 /* BlankZeroFormatter.h */, - 17D1B1630F632ABB00694C57 /* BlankZeroFormatter.m */, - 17D1B1640F632ABB00694C57 /* IndexFormatter.h */, - 17D1B1650F632ABB00694C57 /* IndexFormatter.m */, - 17D1B1660F632ABB00694C57 /* SecondsFormatter.h */, - 17D1B1670F632ABB00694C57 /* SecondsFormatter.m */, - ); - name = Formatters; - sourceTree = ""; - }; 17DDF6400E0CB6F100A2E4AD /* FileTree */ = { isa = PBXGroup; children = ( @@ -1672,6 +1653,15 @@ path = json; sourceTree = ""; }; + 835F00B3279BD1CD00055FCF /* Formatters */ = { + isa = PBXGroup; + children = ( + 835F00B4279BD1CD00055FCF /* SecondsFormatter.h */, + 835F00B8279BD1CD00055FCF /* SecondsFormatter.m */, + ); + path = Formatters; + sourceTree = ""; + }; 8360EF0117F92B23005208A4 /* Products */ = { isa = PBXGroup; children = ( @@ -2496,13 +2486,11 @@ 171EFE8C0F59FEAE000ADC42 /* DockIconController.m in Sources */, 17F6C8070F603701000D9DA9 /* PlaybackEventController.m in Sources */, 83BC5AB220E4C87100631CD4 /* DualWindow.m in Sources */, + 835F00BB279BD1CD00055FCF /* SecondsFormatter.m in Sources */, 1784560F0F631E24007E8021 /* FileTreeViewController.m in Sources */, 178456120F631E31007E8021 /* SideViewController.m in Sources */, 17D1B1010F63255200694C57 /* InfoWindowController.m in Sources */, 835A8FD327957310005B3C39 /* json.c in Sources */, - 17D1B1680F632ABB00694C57 /* BlankZeroFormatter.m in Sources */, - 17D1B1690F632ABB00694C57 /* IndexFormatter.m in Sources */, - 17D1B16A0F632ABB00694C57 /* SecondsFormatter.m in Sources */, 17D1B25D0F633A4F00694C57 /* PreferencePluginController.m in Sources */, 171CB3DC0F63670D0047EF0A /* PreferencesWindow.m in Sources */, 1778D3CA0F645BF00037E7A0 /* MissingAlbumArtTransformer.m in Sources */, diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp index e10b5fabb..e257f988f 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.cpp @@ -174,6 +174,13 @@ unsigned int APE::Tag::track() const return d->itemListMap["TRACK"].toString().toInt(); } +unsigned int APE::Tag::disc() const +{ + if(d->itemListMap["DISC"].isEmpty()) + return 0; + return d->itemListMap["DISC"].toString().toInt(); +} + String APE::Tag::cuesheet() const { if(d->itemListMap["CUESHEET"].isEmpty()) @@ -255,6 +262,14 @@ void APE::Tag::setTrack(unsigned int i) addValue("TRACK", String::number(i), true); } +void APE::Tag::setDisc(unsigned int i) +{ + if(i == 0) + removeItem("DISC"); + else + addValue("DISC", String::number(i), true); +} + void APE::Tag::setCuesheet(const String &) { } diff --git a/Frameworks/TagLib/taglib/taglib/ape/apetag.h b/Frameworks/TagLib/taglib/taglib/ape/apetag.h index f86d7eb1c..872716098 100644 --- a/Frameworks/TagLib/taglib/taglib/ape/apetag.h +++ b/Frameworks/TagLib/taglib/taglib/ape/apetag.h @@ -95,6 +95,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -109,6 +110,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); virtual void setRGAlbumGain(float f); virtual void setRGAlbumPeak(float f); diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp index 95d15f9a7..a9df89eeb 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.cpp @@ -108,6 +108,20 @@ unsigned int ASF::Tag::track() const return 0; } +unsigned int ASF::Tag::disc() const +{ + if(d->attributeListMap.contains("WM/DiscNumber")) { + const ASF::Attribute attr = d->attributeListMap["WM/DiscNumber"][0]; + if(attr.type() == ASF::Attribute::DWordType) + return attr.toUInt(); + else + return attr.toString().toInt(); + } + if(d->attributeListMap.contains("WM/Disc")) + return d->attributeListMap["WM/Disc"][0].toUInt(); + return 0; +} + String ASF::Tag::genre() const { if(d->attributeListMap.contains("WM/Genre")) @@ -189,6 +203,11 @@ void ASF::Tag::setTrack(unsigned int value) setAttribute("WM/TrackNumber", String::number(value)); } +void ASF::Tag::setDisc(unsigned int value) +{ + setAttribute("WM/DiscNumber", String::number(value)); +} + void ASF::Tag::setCuesheet(const String &) { } diff --git a/Frameworks/TagLib/taglib/taglib/asf/asftag.h b/Frameworks/TagLib/taglib/taglib/asf/asftag.h index cfd00cd3b..68f1b4b03 100644 --- a/Frameworks/TagLib/taglib/taglib/asf/asftag.h +++ b/Frameworks/TagLib/taglib/taglib/asf/asftag.h @@ -102,6 +102,7 @@ namespace TagLib { * return 0. */ virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; @@ -160,6 +161,7 @@ namespace TagLib { * Sets the track to \a i. If \a s is 0 then this value will be cleared. */ virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp index 1055955f0..265757dbe 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.cpp @@ -94,6 +94,11 @@ unsigned int Mod::Tag::track() const return 0; } +unsigned int Mod::Tag::disc() const +{ + return 0; +} + String Mod::Tag::cuesheet() const { return String(); @@ -158,6 +163,10 @@ void Mod::Tag::setTrack(unsigned int) { } +void Mod::Tag::setDisc(unsigned int) +{ +} + void Mod::Tag::setCuesheet(const String &) { } diff --git a/Frameworks/TagLib/taglib/taglib/mod/modtag.h b/Frameworks/TagLib/taglib/taglib/mod/modtag.h index d24dd8d4c..16b62e11d 100644 --- a/Frameworks/TagLib/taglib/taglib/mod/modtag.h +++ b/Frameworks/TagLib/taglib/taglib/mod/modtag.h @@ -94,6 +94,11 @@ namespace TagLib { */ virtual unsigned int track() const; + /*! + * Not supported by module files. Therefore always returns 0. + */ + virtual unsigned int disc() const; + /*! * Not supported by module files. Therefore always returns empty. */ @@ -187,6 +192,11 @@ namespace TagLib { */ virtual void setTrack(unsigned int track); + /*! + * Not supported by module files and therefore ignored. + */ + virtual void setDisc(unsigned int track); + /*! * Not supported by module files and therefore ignored. */ diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp index 9bba688ac..7f337e4e6 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.cpp @@ -780,6 +780,14 @@ MP4::Tag::track() const return 0; } +unsigned int +MP4::Tag::disc() const +{ + if(d->items.contains("disk")) + return d->items["disk"].toIntPair().first; + return 0; +} + String MP4::Tag::cuesheet() const { @@ -878,6 +886,17 @@ MP4::Tag::setTrack(unsigned int value) } } +void +MP4::Tag::setDisc(unsigned int value) +{ + if (value == 0) { + d->items.erase("disk"); + } + else { + d->items["disk"] = MP4::Item(value, 0); + } +} + void MP4::Tag::setCuesheet(const String &) { diff --git a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h index e2dbd9f14..60ce51d7d 100644 --- a/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h +++ b/Frameworks/TagLib/taglib/taglib/mp4/mp4tag.h @@ -61,6 +61,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -75,6 +76,7 @@ namespace TagLib { virtual void setGenre(const String &value); virtual void setYear(unsigned int value); virtual void setTrack(unsigned int value); + virtual void setDisc(unsigned int value); virtual void setCuesheet(const String &value); virtual void setRGAlbumGain(float); virtual void setRGAlbumPeak(float); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp index f91b4df0c..847911ab3 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.cpp @@ -167,6 +167,11 @@ unsigned int ID3v1::Tag::track() const return d->track; } +unsigned int ID3v1::Tag::disc() const +{ + return 0; +} + String ID3v1::Tag::cuesheet() const { return String(); @@ -231,6 +236,10 @@ void ID3v1::Tag::setTrack(unsigned int i) d->track = i < 256 ? i : 0; } +void ID3v1::Tag::setDisc(unsigned int i) +{ +} + void ID3v1::Tag::setCuesheet(const String &) { } diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h index f35765f4f..8ad94d9f4 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v1/id3v1tag.h @@ -143,6 +143,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -157,6 +158,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); virtual void setRGAlbumGain(float f); virtual void setRGAlbumPeak(float f); diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp index 47c431002..dfff41d4a 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.cpp @@ -245,6 +245,13 @@ unsigned int ID3v2::Tag::track() const return 0; } +unsigned int ID3v2::Tag::disc() const +{ + if(!d->frameListMap["TPOS"].isEmpty()) + return d->frameListMap["TPOS"].front()->toString().toInt(); + return 0; +} + String ID3v2::Tag::cuesheet() const { const FrameList &list = d->frameListMap["TXXX"]; @@ -396,6 +403,15 @@ void ID3v2::Tag::setTrack(unsigned int i) setTextFrame("TRCK", String::number(i)); } +void ID3v2::Tag::setDisc(unsigned int i) +{ + if (i == 0) { + removeFrames("TPOS"); + return; + } + setTextFrame("TPOS", String::number(i)); +} + void ID3v2::Tag::setCuesheet(const String &s) { bool createdFrame = false; diff --git a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h index 1fd96073d..0e356df32 100644 --- a/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h +++ b/Frameworks/TagLib/taglib/taglib/mpeg/id3v2/id3v2tag.h @@ -164,6 +164,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; @@ -181,6 +182,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp index 7e0f2fbfd..b1d37a2a0 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.cpp @@ -145,6 +145,19 @@ unsigned int Ogg::XiphComment::track() const return d->fieldListMap["TRACKNUMBER"].front().toInt(); if(!d->fieldListMap["TRACKNUM"].isEmpty()) return d->fieldListMap["TRACKNUM"].front().toInt(); + if(!d->fieldListMap["TRACK"].isEmpty()) + return d->fieldListMap["TRACK"].front().toInt(); + return 0; +} + +unsigned int Ogg::XiphComment::disc() const +{ + if(!d->fieldListMap["DISCNUMBER"].isEmpty()) + return d->fieldListMap["DISCNUMBER"].front().toInt(); + if(!d->fieldListMap["DISCNUM"].isEmpty()) + return d->fieldListMap["DISCNUM"].front().toInt(); + if(!d->fieldListMap["DISC"].isEmpty()) + return d->fieldListMap["DISC"].front().toInt(); return 0; } @@ -231,6 +244,7 @@ void Ogg::XiphComment::setYear(unsigned int i) void Ogg::XiphComment::setTrack(unsigned int i) { + removeFields("TRACK"); removeFields("TRACKNUM"); if(i == 0) removeFields("TRACKNUMBER"); @@ -238,6 +252,16 @@ void Ogg::XiphComment::setTrack(unsigned int i) addField("TRACKNUMBER", String::number(i)); } +void Ogg::XiphComment::setDisc(unsigned int i) +{ + removeFields("DISC"); + removeFields("DISCNUM"); + if(i == 0) + removeFields("DISCNUMBER"); + else + addField("DISCNUMBER", String::number(i)); +} + void Ogg::XiphComment::setCuesheet(const String &s) { if (s.isEmpty()) diff --git a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h index 50906f473..a29ce5648 100644 --- a/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h +++ b/Frameworks/TagLib/taglib/taglib/ogg/xiphcomment.h @@ -88,6 +88,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -102,6 +103,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); virtual void setRGAlbumGain(float f); virtual void setRGAlbumPeak(float f); diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp index 65420b1a0..60e0e2a5f 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.cpp @@ -128,6 +128,11 @@ unsigned int RIFF::Info::Tag::track() const return fieldText("IPRT").toInt(); } +unsigned int RIFF::Info::Tag::disc() const +{ + return 0; +} + String RIFF::Info::Tag::cuesheet() const { return String(); @@ -198,6 +203,10 @@ void RIFF::Info::Tag::setTrack(unsigned int i) d->fieldListMap.erase("IPRT"); } +void RIFF::Info::Tag::setDisc(unsigned int) +{ +} + void RIFF::Info::Tag::setCuesheet(const String &) { } diff --git a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h index d3a91a951..4844ba010 100644 --- a/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h +++ b/Frameworks/TagLib/taglib/taglib/riff/wav/infotag.h @@ -110,6 +110,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -124,6 +125,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int); virtual void setCuesheet(const String &s); virtual void setRGAlbumGain(float f); virtual void setRGAlbumPeak(float f); diff --git a/Frameworks/TagLib/taglib/taglib/tag.cpp b/Frameworks/TagLib/taglib/taglib/tag.cpp index 7616d6b6c..9e01e3e80 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.cpp +++ b/Frameworks/TagLib/taglib/taglib/tag.cpp @@ -53,7 +53,8 @@ bool Tag::isEmpty() const comment().isEmpty() && genre().isEmpty() && year() == 0 && - track() == 0); + track() == 0 && + disc() == 0); } PropertyMap Tag::properties() const @@ -75,6 +76,8 @@ PropertyMap Tag::properties() const map["DATE"].append(String::number(year())); if(!(track() == 0)) map["TRACKNUMBER"].append(String::number(track())); + if (!(disc() == 0)) + map["DISCNUMBER"].append(String::number(disc())); return map; } @@ -152,6 +155,18 @@ PropertyMap Tag::setProperties(const PropertyMap &origProps) else setTrack(0); + if(properties.contains("DISCNUMBER")) { + bool ok; + int disc = properties["DISCNUMBER"].front().toInt(&ok); + if(ok) { + setDisc(disc); + oneValueSet.append("DISCNUMBER"); + } else + setDisc(0); + } + else + setDisc(0); + // for each tag that has been set above, remove the first entry in the corresponding // value list. The others will be returned as unsupported by this format. for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) { @@ -174,6 +189,7 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static target->setGenre(source->genre()); target->setYear(source->year()); target->setTrack(source->track()); + target->setDisc(source->disc()); } else { if(target->title().isEmpty()) @@ -192,5 +208,7 @@ void Tag::duplicate(const Tag *source, Tag *target, bool overwrite) // static target->setYear(source->year()); if(target->track() <= 0) target->setTrack(source->track()); + if(target->disc() <= 0) + target->setDisc(source->disc()); } } diff --git a/Frameworks/TagLib/taglib/taglib/tag.h b/Frameworks/TagLib/taglib/taglib/tag.h index 2bcfbadc0..e2c9ac2d2 100644 --- a/Frameworks/TagLib/taglib/taglib/tag.h +++ b/Frameworks/TagLib/taglib/taglib/tag.h @@ -125,6 +125,12 @@ namespace TagLib { */ virtual unsigned int track() const = 0; + /*! + * Returns the disc number; if there is no track number set, this will + * return 0. + */ + virtual unsigned int disc() const = 0; + /*! * Returns the embedded cuesheet; if there is no cuesheet set, this * will return an empty string. @@ -204,6 +210,11 @@ namespace TagLib { */ virtual void setTrack(unsigned int i) = 0; + /*! + * Sets the disc to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setDisc(unsigned int i) = 0; + /*! * Sets the embedded cuesheet to \a s. If \a s is empty then this * value will be cleared. diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.cpp b/Frameworks/TagLib/taglib/taglib/tagunion.cpp index 11171ef65..f892c25a2 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.cpp +++ b/Frameworks/TagLib/taglib/taglib/tagunion.cpp @@ -213,6 +213,11 @@ unsigned int TagUnion::track() const numberUnion(track); } +unsigned int TagUnion::disc() const +{ + numberUnion(disc); +} + String TagUnion::cuesheet() const { stringUnion(cuesheet); @@ -278,6 +283,11 @@ void TagUnion::setTrack(unsigned int i) setUnion(Track, i); } +void TagUnion::setDisc(unsigned int i) +{ + setUnion(Disc, i); +} + void TagUnion::setCuesheet(const String &s) { setUnion(Cuesheet, s); diff --git a/Frameworks/TagLib/taglib/taglib/tagunion.h b/Frameworks/TagLib/taglib/taglib/tagunion.h index c5317b74d..1ceb05f3f 100644 --- a/Frameworks/TagLib/taglib/taglib/tagunion.h +++ b/Frameworks/TagLib/taglib/taglib/tagunion.h @@ -67,6 +67,7 @@ namespace TagLib { virtual String genre() const; virtual unsigned int year() const; virtual unsigned int track() const; + virtual unsigned int disc() const; virtual String cuesheet() const; virtual float rgAlbumGain() const; virtual float rgAlbumPeak() const; @@ -81,6 +82,7 @@ namespace TagLib { virtual void setGenre(const String &s); virtual void setYear(unsigned int i); virtual void setTrack(unsigned int i); + virtual void setDisc(unsigned int i); virtual void setCuesheet(const String &s); virtual void setRGAlbumGain(float f); virtual void setRGAlbumPeak(float f); diff --git a/Playlist/PlaylistController.m b/Playlist/PlaylistController.m index b08b91cf4..c59edbeff 100644 --- a/Playlist/PlaylistController.m +++ b/Playlist/PlaylistController.m @@ -277,7 +277,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc break; case 7: - if ([pe year]) cellText = [NSString stringWithFormat:@"%@", [pe year]]; + if ([pe year]) cellText = [pe yearText]; cellTextAlignment = NSTextAlignmentRight; break; @@ -286,7 +286,7 @@ static inline void dispatch_sync_reentrant(dispatch_queue_t queue, dispatch_bloc break; case 9: - if ([pe track]) cellText = [NSString stringWithFormat:@"%@", [pe track]]; + if ([pe track]) cellText = [pe trackText]; cellTextAlignment = NSTextAlignmentRight; break; diff --git a/Playlist/PlaylistEntry.h b/Playlist/PlaylistEntry.h index a5f8f92cd..aadd1608d 100644 --- a/Playlist/PlaylistEntry.h +++ b/Playlist/PlaylistEntry.h @@ -34,6 +34,7 @@ NSString *genre; NSNumber *year; NSNumber *track; + NSNumber *disc; NSString *cuesheet; @@ -72,6 +73,9 @@ + (NSSet *)keyPathsForValuesAffectingStatusMessage; + (NSSet *)keyPathsForValuesAffectingSpam; + (NSSet *)keyPathsForValuesAffectingAlbumArt; ++ (NSSet *)keyPathsForValuesAffectingTrackText; ++ (NSSet *)keyPathsForValuesAffectingLengthText; ++ (NSSet *)keyPathsForValuesAffectingYearText; @property(readonly) NSString *display; @property(retain, readonly) NSNumber *length; @@ -84,8 +88,12 @@ @property(readonly) NSString *lengthText; +@property(readonly) NSString *yearText; + @property(readonly) NSString *rawTitle; +@property(readonly) NSString *trackText; + @property NSInteger index; @property NSInteger shuffleIndex; @property NSInteger dbIndex; @@ -114,6 +122,7 @@ @property(retain) NSString *genre; @property(retain) NSNumber *year; @property(retain) NSNumber *track; +@property(retain) NSNumber *disc; @property(retain) NSString *cuesheet; diff --git a/Playlist/PlaylistEntry.m b/Playlist/PlaylistEntry.m index a2ed6c7e4..c665cd4cc 100644 --- a/Playlist/PlaylistEntry.m +++ b/Playlist/PlaylistEntry.m @@ -35,6 +35,7 @@ @synthesize genre; @synthesize year; @synthesize track; +@synthesize disc; @synthesize cuesheet; @@ -96,7 +97,12 @@ + (NSSet *)keyPathsForValuesAffectingSpam { - return [NSSet setWithObjects:@"albumartist", @"artist", @"title", @"album", @"track", @"totalFrames", @"currentPosition", @"bitrate", nil]; + return [NSSet setWithObjects:@"albumartist", @"artist", @"title", @"album", @"track", @"disc", @"totalFrames", @"currentPosition", @"bitrate", nil]; +} + ++ (NSSet *)keyPathsForValuesAffectingTrackText +{ + return [NSSet setWithObjects:@"track", @"disc", nil]; } + (NSSet *)keyPathsForValuesAffectingPositionText @@ -144,7 +150,10 @@ self.genre = nil; self.year = nil; self.track = nil; + self.disc = nil; self.albumArtInternal = nil; + + self.cuesheet = nil; self.endian = nil; self.codec = nil; @@ -238,7 +247,7 @@ [elements addObject:self.album]; if (hasTrack) { [elements addObject:@" #"]; - [elements addObject:[NSString stringWithFormat:@"%@", self.track]]; + [elements addObject:self.trackText]; } [elements addObject:@"] "]; } @@ -273,6 +282,39 @@ return [elements componentsJoinedByString:@""]; } +@dynamic trackText; +-(NSString *)trackText +{ + if ([self.track intValue]) + { + if ([self.disc intValue]) + { + return [NSString stringWithFormat:@"%@.%02u", self.disc, [self.track intValue]]; + } + else + { + return [NSString stringWithFormat:@"%02u", [self.track intValue]]; + } + } + else + { + return @""; + } +} + +@dynamic yearText; +-(NSString *)yearText +{ + if ([self.year intValue]) + { + return [NSString stringWithFormat:@"%@", self.year]; + } + else + { + return @""; + } +} + @dynamic positionText; - (NSString *)positionText { @@ -424,6 +466,7 @@ pe->genre = [genre copyWithZone:zone]; pe->year = [year copyWithZone:zone]; pe->track = [track copyWithZone:zone]; + pe->disc = [disc copyWithZone:zone]; pe->cuesheet = [cuesheet copyWithZone:zone]; diff --git a/Playlist/PlaylistView.m b/Playlist/PlaylistView.m index fec874902..6e4613494 100644 --- a/Playlist/PlaylistView.m +++ b/Playlist/PlaylistView.m @@ -10,10 +10,7 @@ #import -#import "BlankZeroFormatter.h" -#import "IndexFormatter.h" #import "PlaylistEntry.h" -#import "SecondsFormatter.h" #import "CogAudio/Status.h" @@ -47,18 +44,6 @@ [[col dataCell] setFont:f]; } - // Set up formatters - NSFormatter *secondsFormatter = [[SecondsFormatter alloc] init]; - [[[self tableColumnWithIdentifier:@"length"] dataCell] setFormatter:secondsFormatter]; - - NSFormatter *indexFormatter = [[IndexFormatter alloc] init]; - [[[self tableColumnWithIdentifier:@"index"] dataCell] setFormatter:indexFormatter]; - - NSFormatter *blankZeroFormatter = [[BlankZeroFormatter alloc] init]; - [[[self tableColumnWithIdentifier:@"track"] dataCell] setFormatter:blankZeroFormatter]; - [[[self tableColumnWithIdentifier:@"year"] dataCell] setFormatter:blankZeroFormatter]; - // end setting up formatters - [self setVerticalMotionCanBeginDrag:YES]; // Set up header context menu diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index 6290dc65d..b5050515a 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -265,6 +265,14 @@ static int psf_info_meta(void * context, const char * name, const char * value) { taglc = @"albumartist"; } + else if ([taglc isEqualToString:@"tracknumber"]) + { + taglc = @"track"; + } + else if ([taglc isEqualToString:@"discnumber"]) + { + taglc = @"disc"; + } if ([taglc hasPrefix:@"replaygain_"]) { @@ -305,7 +313,8 @@ static int psf_info_meta(void * context, const char * name, const char * value) [taglc isEqualToString:@"album"] || [taglc isEqualToString:@"year"] || [taglc isEqualToString:@"genre"] || - [taglc isEqualToString:@"track"]) + [taglc isEqualToString:@"track"] || + [taglc isEqualToString:@"disc"]) { [state->info setObject:svalue forKey:taglc]; } diff --git a/Plugins/TagLib/TagLibMetadataReader.m b/Plugins/TagLib/TagLibMetadataReader.m index ec40d6122..8c9776902 100644 --- a/Plugins/TagLib/TagLibMetadataReader.m +++ b/Plugins/TagLib/TagLibMetadataReader.m @@ -72,7 +72,7 @@ if (tag) { TagLib::String artist, albumartist, title, album, genre, comment; - int year, track; + int year, track, disc; float rgAlbumGain, rgAlbumPeak, rgTrackGain, rgTrackPeak; TagLib::String cuesheet; @@ -89,6 +89,9 @@ track = tag->track(); [dict setObject:[NSNumber numberWithInt:track] forKey:@"track"]; + + disc = tag->disc(); + [dict setObject:[NSNumber numberWithInt:disc] forKey:@"disc"]; rgAlbumGain = tag->rgAlbumGain(); rgAlbumPeak = tag->rgAlbumPeak(); diff --git a/Plugins/TagLib/TagLibMetadataWriter.m b/Plugins/TagLib/TagLibMetadataWriter.m index 3c676c9fa..414eaf2e8 100644 --- a/Plugins/TagLib/TagLibMetadataWriter.m +++ b/Plugins/TagLib/TagLibMetadataWriter.m @@ -59,6 +59,7 @@ lYear = tag->year(); lTrack = tag->track(); + lDisc = tag->disc(); if (!pArtist.isNull()) lArtist = [NSString stringWithUTF8String:pArtist.toCString(true)]; diff --git a/Plugins/vgmstream/vgmstream/VGMDecoder.m b/Plugins/vgmstream/vgmstream/VGMDecoder.m index af2a894ca..649c31814 100644 --- a/Plugins/vgmstream/vgmstream/VGMDecoder.m +++ b/Plugins/vgmstream/vgmstream/VGMDecoder.m @@ -95,6 +95,7 @@ static NSString* get_description_tag(const char* description, const char *tag, c NSString *artist = @""; NSNumber *year = [NSNumber numberWithInt:0]; NSNumber *track = [NSNumber numberWithInt:0]; + NSNumber *disc = [NSNumber numberWithInt:0]; NSString *title = @""; NSString *codec; @@ -146,6 +147,10 @@ static NSString* get_description_tag(const char* description, const char *tag, c !strcasecmp(tag_key, "TRACKNUMBER")) { track = [NSNumber numberWithInt:[value intValue]]; } + else if (!strcasecmp(tag_key, "DISC") || + !strcasecmp(tag_key, "DISCNUMBER")) { + disc = [NSNumber numberWithInt:[value intValue]]; + } else if (!strcasecmp(tag_key, "TITLE")) { title = value; } @@ -186,6 +191,7 @@ static NSString* get_description_tag(const char* description, const char *tag, c [NSMutableDictionary dictionaryWithObjectsAndKeys: title, @"title", track, @"track", + disc, @"disc", nil]; if ( ![album isEqualToString:@""] ) diff --git a/Utils/SQLiteStore.m b/Utils/SQLiteStore.m index 512e0a39a..3c5f74791 100644 --- a/Utils/SQLiteStore.m +++ b/Utils/SQLiteStore.m @@ -1031,7 +1031,7 @@ static SQLiteStore *g_sharedStore = NULL; int64_t titleId = [self addString:[track rawTitle]]; int64_t genreId = [self addString:[track genre]]; int64_t codecId = [self addString:[track codec]]; - int64_t trackNr = [[track track] intValue]; + int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32); int64_t year = [[track year] intValue]; int64_t unsignedFmt = [track Unsigned]; int64_t bitrate = [track bitrate]; @@ -1223,7 +1223,7 @@ static SQLiteStore *g_sharedStore = NULL; int64_t titleId = [self addString:[track rawTitle]]; int64_t genreId = [self addString:[track genre]]; int64_t codecId = [self addString:[track codec]]; - int64_t trackNr = [[track track] intValue]; + int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32); int64_t year = [[track year] intValue]; int64_t unsignedFmt = [track Unsigned]; int64_t bitrate = [track bitrate]; @@ -1348,6 +1348,9 @@ static SQLiteStore *g_sharedStore = NULL; double replaygainalbumpeak = sqlite3_column_double(st, select_track_data_out_replaygainalbumpeak); double replaygaintrackgain = sqlite3_column_double(st, select_track_data_out_replaygaintrackgain); double replaygaintrackpeak = sqlite3_column_double(st, select_track_data_out_replaygaintrackpeak); + + uint64_t discNr = ((uint64_t)trackNr) >> 32; + trackNr &= (1UL << 32) - 1; [entry setURL:urlForPath([self getString:urlId])]; @@ -1358,6 +1361,7 @@ static SQLiteStore *g_sharedStore = NULL; [entry setGenre:[self getString:genreId]]; [entry setCodec:[self getString:codecId]]; [entry setTrack:[NSNumber numberWithInteger:trackNr]]; + [entry setDisc:[NSNumber numberWithInteger:discNr]]; [entry setYear:[NSNumber numberWithInteger:year]]; [entry setUnsigned:!!unsignedFmt]; [entry setBitrate:(int)bitrate];