diff --git a/CHANGELOG.md b/CHANGELOG.md index 4be06da..c323b08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ Changelog ======= +### 1.5.4 +- Add info about number of audio channels. +- Bugfix tracks (audio, video, subtitle) menu. +- Experimental support for macOS 10.14. + ### 1.5.3 - Bugfix for chapters. @@ -24,9 +29,9 @@ Changelog ### 1.0.0 - Universal binary support (_but `ffmpeg` for arm64 is compiled on intel platform without assembly optimizations_). -- Support for automatic Sparke update. +- Support for automatic Sparkle update. - New app icon. -- Removed App Group capability to handle the settings (App Group _require_ codesign). Settings are now handled with an XPC service. +- Removed App Group capability to handle the settings (App Group _require_ code sign). Settings are now handled with an XPC service. ### 1.0.b11 diff --git a/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/Contents.json b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/Contents.json new file mode 100644 index 0000000..9733e5b --- /dev/null +++ b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "speaker_mono.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/speaker_mono.pdf b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/speaker_mono.pdf new file mode 100644 index 0000000..b0789f0 Binary files /dev/null and b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_mono.imageset/speaker_mono.pdf differ diff --git a/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/Contents.json b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/Contents.json new file mode 100644 index 0000000..67581b9 --- /dev/null +++ b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "speaker_stereo.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/speaker_stereo.pdf b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/speaker_stereo.pdf new file mode 100644 index 0000000..f22fe06 Binary files /dev/null and b/MediaInfo Finder Extension/Assets_menu.xcassets/speaker_stereo.imageset/speaker_stereo.pdf differ diff --git a/MediaInfo Finder Extension/MediaInfo_Finder_Extension.entitlements b/MediaInfo Finder Extension/MediaInfo_Finder_Extension.entitlements index 10d57e7..6e7e756 100644 --- a/MediaInfo Finder Extension/MediaInfo_Finder_Extension.entitlements +++ b/MediaInfo Finder Extension/MediaInfo_Finder_Extension.entitlements @@ -7,8 +7,6 @@ com.apple.security.files.user-selected.read-only com.apple.security.temporary-exception.files.home-relative-path.read-only - - / - + diff --git a/MediaInfo Finder Extension/it.lproj/LocalizableExt.strings b/MediaInfo Finder Extension/it.lproj/LocalizableExt.strings index a076ab6..8d06959 100644 --- a/MediaInfo Finder Extension/it.lproj/LocalizableExt.strings +++ b/MediaInfo Finder Extension/it.lproj/LocalizableExt.strings @@ -95,3 +95,8 @@ "last saved by %@" = "ultimo salvataggio di %@"; "last saved on %@" = "ultimo salvataggio il %@"; "on %@" = "il %@"; + +"mono" = "mono"; +"stereo" = "stereo"; +"1 channel" = "1 canale"; +"%d channels" = "%d canali"; diff --git a/MediaInfo.xcodeproj/project.pbxproj b/MediaInfo.xcodeproj/project.pbxproj index 08f24d4..6fbccbd 100644 --- a/MediaInfo.xcodeproj/project.pbxproj +++ b/MediaInfo.xcodeproj/project.pbxproj @@ -11264,7 +11264,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -11281,7 +11281,8 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfo; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -11299,7 +11300,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -11316,7 +11317,8 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfo; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -11332,7 +11334,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_ASSET_PATHS = "MediaInfo\\ Finder\\ Extension/Assets_menu.xcassets"; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -11347,7 +11349,8 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = "org.sbarex.MediaInfo.Finder-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -11364,7 +11367,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_ASSET_PATHS = "MediaInfo\\ Finder\\ Extension/Assets_menu.xcassets"; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; @@ -11379,7 +11382,8 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = "org.sbarex.MediaInfo.Finder-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -11439,7 +11443,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ( @@ -11459,7 +11463,8 @@ "$(BUILT_PRODUCTS_DIR)/libwebp", "$(inherited)", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfoHelperXPC; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -11477,7 +11482,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ( @@ -11497,7 +11502,8 @@ "$(BUILT_PRODUCTS_DIR)/libwebp", "$(inherited)", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfoHelperXPC; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -11514,7 +11520,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ( @@ -11534,7 +11540,8 @@ "$(BUILT_PRODUCTS_DIR)/libwebp", "$(inherited)", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfoSettingsXPC; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -11550,7 +11557,7 @@ CODE_SIGN_INJECT_BASE_ENTITLEMENTS = NO; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 16; + CURRENT_PROJECT_VERSION = 17; DEVELOPMENT_TEAM = ""; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ( @@ -11570,7 +11577,8 @@ "$(BUILT_PRODUCTS_DIR)/libwebp", "$(inherited)", ); - MARKETING_VERSION = 1.5.3; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.5.4; OTHER_CODE_SIGN_FLAGS = "--timestamp"; PRODUCT_BUNDLE_IDENTIFIER = org.sbarex.MediaInfoSettingsXPC; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/MediaInfo/Assets.xcassets/speaker.imageset/Contents.json b/MediaInfo/Assets.xcassets/speaker.imageset/Contents.json new file mode 100644 index 0000000..9733e5b --- /dev/null +++ b/MediaInfo/Assets.xcassets/speaker.imageset/Contents.json @@ -0,0 +1,16 @@ +{ + "images" : [ + { + "filename" : "speaker_mono.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" + } +} diff --git a/MediaInfo/Assets.xcassets/speaker.imageset/speaker_mono.pdf b/MediaInfo/Assets.xcassets/speaker.imageset/speaker_mono.pdf new file mode 100644 index 0000000..b0789f0 Binary files /dev/null and b/MediaInfo/Assets.xcassets/speaker.imageset/speaker_mono.pdf differ diff --git a/MediaInfo/MenuItemEditor.swift b/MediaInfo/MenuItemEditor.swift index a1c1eca..514d572 100644 --- a/MediaInfo/MenuItemEditor.swift +++ b/MediaInfo/MenuItemEditor.swift @@ -56,6 +56,9 @@ class MenuItemEditor: NSViewController { Image(name: "size", title: NSLocalizedString("File size", comment: "")), Image(name: "print", title: NSLocalizedString("Printer", comment: "")), Image(name: "person", title: NSLocalizedString("Person", comment: "")), + Image(name: "speaker", title: NSLocalizedString("Speaker (mono or stereo)", comment: "")), + Image(name: "speaker_mono", title: NSLocalizedString("Speaker", comment: "")), + Image(name: "speaker_stereo", title: NSLocalizedString("Speakers", comment: "")), Image.separator(), Image(name: "color", title: NSLocalizedString("Color", comment: "")), diff --git a/MediaInfo/Settings.swift b/MediaInfo/Settings.swift index f2c92e0..b83b6ab 100644 --- a/MediaInfo/Settings.swift +++ b/MediaInfo/Settings.swift @@ -107,7 +107,7 @@ class Settings { MenuItem(image: "size", template: "[[filesize]]"), ] settings.audioMenuItems = [ - MenuItem(image: "audio", template: "[[duration]] ([[seconds]]) [[language-flag]]"), + MenuItem(image: "audio", template: "[[duration]] ([[seconds]]) [[channels-name]] [[language-flag]]"), MenuItem(image: "audio", template: "[[bitrate]], [[codec]]"), MenuItem(image: "tag", template: "[[title]]"), MenuItem(image: "", template: "([[engine]])"), diff --git a/MediaInfo/Tokens/TokenVideoMetadata.swift b/MediaInfo/Tokens/TokenVideoMetadata.swift index f3c27f1..9e0530c 100644 --- a/MediaInfo/Tokens/TokenVideoMetadata.swift +++ b/MediaInfo/Tokens/TokenVideoMetadata.swift @@ -138,6 +138,8 @@ class TokenAudioMetadata: Token { case encoder case chapters case chaptersCount + case channels + case channels_name static var pasteboardType: NSPasteboard.PasteboardType { return .MITokenAudioMetadata @@ -149,6 +151,8 @@ class TokenAudioMetadata: Token { case .encoder: return "encoder" case .chaptersCount: return String(format: NSLocalizedString("%d Chapters", tableName: "LocalizableExt", comment: ""), 2) case .chapters: return NSLocalizedString("Chapters list", comment: "") + case .channels: return NSLocalizedString("1 channel", tableName: "LocalizableExt", comment: "") + case .channels_name: return NSLocalizedString("mono", tableName: "LocalizableExt", comment: "") } } @@ -158,6 +162,8 @@ class TokenAudioMetadata: Token { case .encoder: return "[[encoder]]" case .chaptersCount: return "[[chapters-count]]" case .chapters: return "[[chapters]]" + case .channels: return "[[channels]]" + case .channels_name: return "[[channels-name]]" } } @@ -167,6 +173,8 @@ class TokenAudioMetadata: Token { case .encoder: return NSLocalizedString("Encoder.", comment: "") case .chapters: return NSLocalizedString("List of chapters.", comment: "") case .chaptersCount: return NSLocalizedString("Number of chapters.", comment: "") + case .channels: return NSLocalizedString("Number of channels.", comment: "") + case .channels_name: return NSLocalizedString("Mono, Stereo, or number of channels.", comment: "") } } @@ -176,7 +184,8 @@ class TokenAudioMetadata: Token { case "[[encoder]]": self = .encoder case "[[chapters]]": self = .chapters case "[[chapters-count]]": self = .chaptersCount - + case "[[channels]]": self = .channels + case "[[channels-name]]": self = .channels_name default: return nil } } diff --git a/MediaInfo/ViewController.swift b/MediaInfo/ViewController.swift index 755797c..310efd4 100644 --- a/MediaInfo/ViewController.swift +++ b/MediaInfo/ViewController.swift @@ -235,7 +235,7 @@ class ViewController: NSViewController { isLossless: false, chapters: [Chapter(title: "title1", start: 0, end: 200), Chapter(title: "title2", start: 201, end: 600)], video: [], audio: [ - AudioTrackInfo(duration: 3600, start_time: 0, codec_short_name: "mp3", codec_long_name: "MP3 (MPEG audio layer 3)", lang: "EN", bitRate: 512*1025, title: "Audio title", encoder: "Encoder", isLossless: false) + AudioTrackInfo(duration: 3600, start_time: 0, codec_short_name: "mp3", codec_long_name: "MP3 (MPEG audio layer 3)", lang: "EN", bitRate: 512*1025, title: "Audio title", encoder: "Encoder", isLossless: false, channels: 2) ], subtitles: [ SubtitleTrackInfo(title: "English subtitle", lang: "EN"), SubtitleTrackInfo(title: "Sottitoli in italiano", lang: "IT"), @@ -265,6 +265,7 @@ class ViewController: NSViewController { title: "Audio title", encoder: "Encoder", isLossless: false, chapters: [], + channels: 2, engine: .coremedia) } diff --git a/MediaInfo/it.lproj/Localizable.strings b/MediaInfo/it.lproj/Localizable.strings index 632feba..15c51ed 100644 --- a/MediaInfo/it.lproj/Localizable.strings +++ b/MediaInfo/it.lproj/Localizable.strings @@ -127,6 +127,8 @@ "sheets" = "fogli"; "Page size (for document files)." = "Dimensioni sulla pagina (per documenti di testo)."; "Page format or page size (for document files)." = "Formato pagina o sue dimensioni (per documenti di testo)."; +"Number of channels." = "Numero di canali"; +"Mono, Stereo, or number of channels." = "Mono, Stereo, o numbero di canali."; // MARK: - "Number of audio tracks." = "Numero di tracce audio."; @@ -177,6 +179,9 @@ "PDF" = "PDF"; "Printer" = "Stampante"; "Person" = "Persona"; +"Speaker (mono or stereo)" = "Altoparlante (mono o stereo)"; +"Speaker" = "Altoparlante"; +"Speakers" = "Altoparlanti"; "Color" = "Colore"; "Black and White" = "Bianco e nero"; "Gray scale" = "Scala di grigio"; diff --git a/MediaInfoHelperXPC/CGMediaUtils.swift b/MediaInfoHelperXPC/CGMediaUtils.swift index 79c0848..f2b53f2 100644 --- a/MediaInfoHelperXPC/CGMediaUtils.swift +++ b/MediaInfoHelperXPC/CGMediaUtils.swift @@ -258,6 +258,7 @@ func getCMMediaInfo(forFile file: URL) -> MediaInfo? { encoder: encoder ?? a.encoder, isLossless: a.isLossless, chapters: chapters, + channels: a.channels, engine: .coremedia ) return audio @@ -303,13 +304,20 @@ func getCMMediaStreams(forFile file: URL) -> [BaseInfo] { let numberOfFrames = Int((durationInSeconds * framesPerSecond).rounded()) // let d = track.formatDescriptions.first as! CMVideoFormatDescription let formatDescriptions = track.formatDescriptions as! [CMFormatDescription] - let formatDesc = formatDescriptions.first + var mediaType: FourCharCode? + if let formatDesc = formatDescriptions.first { + if #available(macOS 10.15, *) { + mediaType = formatDesc.mediaSubType.rawValue + } else { + mediaType = CMFormatDescriptionGetMediaSubType(formatDesc) + } + } let v = VideoTrackInfo( width: Int(track.naturalSize.width), height: Int(track.naturalSize.height), duration: durationInSeconds, start_time: startTime, - codec_short_name: codecForVideoCode(formatDesc?.mediaSubType.rawValue) ?? "", - codec_long_name: longCodecForVideoCode(formatDesc?.mediaSubType.rawValue), + codec_short_name: codecForVideoCode(mediaType) ?? "", + codec_long_name: longCodecForVideoCode(mediaType), profile: nil, pixel_format: nil, color_space: nil, field_order: nil, lang: lang, @@ -326,17 +334,30 @@ func getCMMediaStreams(forFile file: URL) -> [BaseInfo] { let durationInSeconds = CMTimeGetSeconds(track.timeRange.duration) let startTime = CMTimeGetSeconds(track.timeRange.start) let formatDescriptions = track.formatDescriptions as! [CMFormatDescription] - let formatDesc = formatDescriptions.first + + var channels = -1 + var mediaType: FourCharCode? = nil + if let formatDesc = formatDescriptions.first { + if let basic = CMAudioFormatDescriptionGetStreamBasicDescription(formatDesc) { + channels = Int(basic.pointee.mChannelsPerFrame) + } + if #available(macOS 10.15, *) { + mediaType = formatDesc.mediaSubType.rawValue + } else { + mediaType = CMFormatDescriptionGetMediaSubType(formatDesc) + } + } let a = AudioTrackInfo( duration: durationInSeconds, start_time: startTime, - codec_short_name: codecForVideoCode(formatDesc?.mediaSubType.rawValue) ?? "", - codec_long_name: longCodecForVideoCode(formatDesc?.mediaSubType.rawValue), + codec_short_name: codecForVideoCode(mediaType) ?? "", + codec_long_name: longCodecForVideoCode(mediaType), lang: lang, bitRate: Int64(track.estimatedDataRate), title: title, encoder: encoder, - isLossless: nil + isLossless: nil, + channels: channels ) streams.append(a) diff --git a/MediaInfoHelperXPC/FFMpegMediaUtils.swift b/MediaInfoHelperXPC/FFMpegMediaUtils.swift index 054a612..a1367a9 100644 --- a/MediaInfoHelperXPC/FFMpegMediaUtils.swift +++ b/MediaInfoHelperXPC/FFMpegMediaUtils.swift @@ -431,6 +431,7 @@ func getFFMpegAudioInfo(forFile file: URL) -> AudioInfo? { title: title ?? a.title, encoder: encoder ?? a.encoder, isLossless: a.isLossless, chapters: chapters, + channels: a.channels, engine: .ffmpeg ) return audio @@ -611,7 +612,8 @@ func getFFMpegMediaStreams(forFile file: URL, with pFormatCtx: inout UnsafeMutab lang: lang, bitRate: bit_rate, title: title, encoder: encoder, - isLossless: isLossless + isLossless: isLossless, + channels: Int(avctx!.pointee.channels) ) streams.append(a) diff --git a/MediaInfoHelperXPC/MetadataMediaUtils.swift b/MediaInfoHelperXPC/MetadataMediaUtils.swift index 347c512..4350703 100644 --- a/MediaInfoHelperXPC/MetadataMediaUtils.swift +++ b/MediaInfoHelperXPC/MetadataMediaUtils.swift @@ -105,6 +105,7 @@ func getMetadataAudioInfo(forFile file: URL) -> AudioInfo? { encoder: a.encoder, isLossless: a.isLossless, chapters: [], + channels: a.channels, engine: .metadata ) return audio @@ -174,6 +175,12 @@ func getMetadataMediaStreams(forFile file: URL, withMetadata metadata: MDItem) - CFNumberGetValue((n as! CFNumber), CFNumberType.sInt64Type, &audioBitRate) } + var channels: Int = 0 + if let n = MDItemCopyAttribute(metadata, kMDItemAudioChannelCount) { + CFNumberGetValue((n as! CFNumber), CFNumberType.sInt64Type, &channels) + } + + for (i, type) in types.enumerated() { let codec = i < codecs.count ? codecs[i] : "" let lang = i < langs.count ? langs[i] : nil @@ -193,16 +200,18 @@ func getMetadataMediaStreams(forFile file: URL, withMetadata metadata: MDItem) - bitRate: videoBitRate, fps: 0, frames: 0, title: nil, encoder: nil, - isLossless: nil) + isLossless: nil + ) streams.append(v) case "Sound": let a = AudioTrackInfo( - duration: duration, start_time: -1, - codec_short_name: codec, codec_long_name: nil, - lang: lang, - bitRate: audioBitRate, - title: nil, encoder: nil, - isLossless: nil + duration: duration, start_time: -1, + codec_short_name: codec, codec_long_name: nil, + lang: lang, + bitRate: audioBitRate, + title: nil, encoder: nil, + isLossless: nil, + channels: channels ) streams.append(a) default: diff --git a/MediaInfoHelperXPC/info/BaseInfoItems.swift b/MediaInfoHelperXPC/info/BaseInfoItems.swift index 688c24a..44ea7c0 100644 --- a/MediaInfoHelperXPC/info/BaseInfoItems.swift +++ b/MediaInfoHelperXPC/info/BaseInfoItems.swift @@ -89,6 +89,8 @@ class BaseInfo: NSCoding { img = NSImage(named: "ppt") case "abc": img = NSImage(named: "abc") + case "speaker": + img = NSImage(named: "speaker_mono") default: img = NSImage(named: mode) } diff --git a/MediaInfoHelperXPC/info/MediaInfoItems.swift b/MediaInfoHelperXPC/info/MediaInfoItems.swift index 098e850..eb151cb 100644 --- a/MediaInfoHelperXPC/info/MediaInfoItems.swift +++ b/MediaInfoHelperXPC/info/MediaInfoItems.swift @@ -1153,7 +1153,7 @@ class VideoInfo: VideoTrackInfo, MediaInfo, ChaptersInfo { return s case "[[audio-count]]": let s = format(value: values?["audio"] ?? self.audioTracks, isFilled: &isFilled) { v, isFilled in - guard let audio = v as? [AudioInfo] else { + guard let audio = v as? [AudioTrackInfo] else { isFilled = false return self.formatERR(useEmptyData: useEmptyData) } @@ -1240,16 +1240,15 @@ class VideoInfo: VideoTrackInfo, MediaInfo, ChaptersInfo { let group_tracks = settings.isTracksGrouped // FIXME: rename let video_sub_menu: NSMenu + var title = "" if group_tracks { var filled = false - var title = self.replacePlaceholders(in: "[[video-count]]", settings: settings, isFilled: &filled) + title = self.replacePlaceholders(in: "[[video-count]]", settings: settings, isFilled: &filled) if !filled || title.isEmpty { title = NSLocalizedString("Video", tableName: "LocalizableExt", comment: "") } - let video_mnu = destination_sub_menu.addItem(withTitle: title, action: nil, keyEquivalent: "") - video_mnu.image = self.getImage(for: "video") video_sub_menu = NSMenu(title: title) - destination_sub_menu.setSubmenu(video_sub_menu, for: video_mnu) + } else { video_sub_menu = destination_sub_menu } @@ -1261,6 +1260,15 @@ class VideoInfo: VideoTrackInfo, MediaInfo, ChaptersInfo { video_sub_menu.addItem(item.copy() as! NSMenuItem) } } + if group_tracks { + if n == 1 && settings.isInfoOnMainItem && video_sub_menu.items.count == 1 { + destination_sub_menu.addItem(video_sub_menu.items.first!.copy() as! NSMenuItem) + } else { + let video_mnu = destination_sub_menu.addItem(withTitle: title, action: nil, keyEquivalent: "") + video_mnu.image = self.getImage(for: "video") + destination_sub_menu.setSubmenu(video_sub_menu, for: video_mnu) + } + } case "[[audio]]": let n = audioTracks.count guard n > 0 else { @@ -1268,20 +1276,20 @@ class VideoInfo: VideoTrackInfo, MediaInfo, ChaptersInfo { } let audio_sub_menu: NSMenu - let group_tracks = settings.isTracksGrouped // FIXME: rename + let group_tracks = settings.isTracksGrouped + var title = "" if group_tracks { var filled = false - var title = self.replacePlaceholders(in: "[[audio-count]]", settings: settings, isFilled: &filled) + title = self.replacePlaceholders(in: "[[audio-count]]", settings: settings, isFilled: &filled) if !filled || title.isEmpty { title = NSLocalizedString("Audio", tableName: "LocalizableExt", comment: "") } - let audio_mnu = destination_sub_menu.addItem(withTitle: title, action: nil, keyEquivalent: "") - audio_mnu.image = self.getImage(for: "audio") + audio_sub_menu = NSMenu(title: title) - destination_sub_menu.setSubmenu(audio_sub_menu, for: audio_mnu) } else { audio_sub_menu = destination_sub_menu } + for audio in audioTracks { guard let audio_menu = audio.getMenu(withSettings: settings) else { continue @@ -1290,9 +1298,22 @@ class VideoInfo: VideoTrackInfo, MediaInfo, ChaptersInfo { audio_sub_menu.addItem(item.copy() as! NSMenuItem) } } + if group_tracks { + if n == 1 && settings.isInfoOnMainItem && audio_sub_menu.items.count == 1 { + destination_sub_menu.addItem(audio_sub_menu.items.first!.copy() as! NSMenuItem) + } else { + let audio_mnu = destination_sub_menu.addItem(withTitle: title, action: nil, keyEquivalent: "") + audio_mnu.image = self.getImage(for: "audio") + destination_sub_menu.setSubmenu(audio_sub_menu, for: audio_mnu) + } + } case "[[subtitles]]": - let sub_menu_txt: NSMenu let n = subtitles.count + guard n > 0 else { + return true + } + + let sub_menu_txt: NSMenu let group_tracks = settings.isTracksGrouped // FIXME: rename if group_tracks { let mnu_txt = destination_sub_menu.addItem(withTitle: "\(n) " + NSLocalizedString("Subtitles", tableName: "LocalizableExt", comment: ""), action: nil, keyEquivalent: "") @@ -1390,8 +1411,15 @@ class AudioTrackInfo: BaseInfo, LanguageInfo, DurationInfo, CodecInfo { let title: String? let encoder: String? let isLossless: Bool? + let channels: Int + var isMono: Bool { + return channels == 1 + } + var isStereo: Bool { + return channels == 2 + } - init(duration: Double, start_time: Double, codec_short_name: String, codec_long_name: String?, lang: String?, bitRate: Int64, title: String?, encoder: String?, isLossless: Bool?) { + init(duration: Double, start_time: Double, codec_short_name: String, codec_long_name: String?, lang: String?, bitRate: Int64, title: String?, encoder: String?, isLossless: Bool?, channels: Int) { self.duration = duration self.start_time = start_time self.codec_short_name = codec_short_name @@ -1401,6 +1429,7 @@ class AudioTrackInfo: BaseInfo, LanguageInfo, DurationInfo, CodecInfo { self.isLossless = isLossless self.title = title self.encoder = encoder + self.channels = channels super.init() } @@ -1414,6 +1443,7 @@ class AudioTrackInfo: BaseInfo, LanguageInfo, DurationInfo, CodecInfo { self.title = coder.decodeObject(forKey: "title") as? String self.encoder = coder.decodeObject(forKey: "encoder") as? String self.isLossless = coder.decodeObject(forKey: "isLossless") as? Bool + self.channels = coder.decodeInteger(forKey: "channels") super.init(coder: coder) } @@ -1427,11 +1457,21 @@ class AudioTrackInfo: BaseInfo, LanguageInfo, DurationInfo, CodecInfo { coder.encode(self.title, forKey: "title") coder.encode(self.encoder, forKey: "encoder") coder.encode(self.isLossless, forKey: "isLossless") + coder.encode(self.channels, forKey: "channels") super.encode(with: coder) } + override func getImage(for name: String) -> NSImage? { + if name == "speaker" && self.isStereo { + return super.getImage(for: "speaker_stereo"); + } else { + return super.getImage(for: name) + } + } + override internal func processPlaceholder(_ placeholder: String, settings: Settings, values: [String : Any]? = nil, isFilled: inout Bool) -> String { + let useEmptyData = false switch placeholder { case "[[duration]]", "[[seconds]]", "[[bitrate]]", "[[start-time]]", "[[start-time-s]]": return processDurationPlaceholder(placeholder, values: values, isFilled: &isFilled) @@ -1443,6 +1483,39 @@ class AudioTrackInfo: BaseInfo, LanguageInfo, DurationInfo, CodecInfo { "[[chapters-count]]", "[[engine]]": isFilled = false return "" + case "[[channels]]": + return format(value: values?["channels"] ?? self.channels, isFilled: &isFilled) { v, isFilled in + guard let channels = v as? Int else { + isFilled = false + return self.formatERR(useEmptyData: useEmptyData) + } + isFilled = channels > 0 + if channels <= 0 { + return self.formatND(useEmptyData: useEmptyData) + } else if channels == 1 { + return NSLocalizedString("1 channel", tableName: "LocalizableExt", comment: "") + } else { + return String(format: NSLocalizedString("%d channels", tableName: "LocalizableExt", comment: ""), channels) + } + } + + case "[[channels-name]]": + return format(value: values?["channels"] ?? self.channels, isFilled: &isFilled) { v, isFilled in + guard let channels = v as? Int else { + isFilled = false + return self.formatERR(useEmptyData: useEmptyData) + } + isFilled = channels > 0 + if channels <= 0 { + return self.formatND(useEmptyData: useEmptyData) + } else if channels == 1 { + return NSLocalizedString("mono", tableName: "LocalizableExt", comment: "") + } else if channels == 2 { + return NSLocalizedString("stereo", tableName: "LocalizableExt", comment: "") + } else { + return String(format: NSLocalizedString("%d channels", tableName: "LocalizableExt", comment: ""), channels) + } + } default: return super.processPlaceholder(placeholder, settings: settings, values: values, isFilled: &isFilled) } @@ -1476,13 +1549,13 @@ class AudioInfo: AudioTrackInfo, MediaInfo, ChaptersInfo { let chapters: [Chapter] let engine: MediaEngine - init(file: URL, duration: Double, start_time: Double, codec_short_name: String, codec_long_name: String?, lang: String?, bitRate: Int64, title: String?, encoder: String?, isLossless: Bool?, chapters: [Chapter], engine: MediaEngine) { + init(file: URL, duration: Double, start_time: Double, codec_short_name: String, codec_long_name: String?, lang: String?, bitRate: Int64, title: String?, encoder: String?, isLossless: Bool?, chapters: [Chapter], channels: Int, engine: MediaEngine) { self.file = file self.fileSize = Self.getFileSize(file) ?? -1 self.chapters = chapters self.engine = engine - super.init(duration: duration, start_time: start_time, codec_short_name: codec_short_name, codec_long_name: codec_long_name, lang: lang, bitRate: bitRate, title: title, encoder: encoder, isLossless: isLossless) + super.init(duration: duration, start_time: start_time, codec_short_name: codec_short_name, codec_long_name: codec_long_name, lang: lang, bitRate: bitRate, title: title, encoder: encoder, isLossless: isLossless, channels: channels) } required init?(coder: NSCoder) { diff --git a/README.md b/README.md index d6dac6e..196c981 100644 --- a/README.md +++ b/README.md @@ -183,6 +183,8 @@ Available information: |codec|Codec name (full name if available, otherwise short name).|_MPEG audio layer 2/3_| |codec short name|Codec short name.|_mp3_| |codec long name|Codec long name.|_MPEG audio layer 2/3_| +|channels|Number of channels|_2 channels_| +|channels|Audio mono, stereo or number of channels|_Mono_, _Stereo_, _3 channels_, …| |chapters|Number of chapters.|_2 chapters_ If this placeholder is the only in the menu item will be added a submenu with the list of the chapters.| |title|Title.|| |encoder|Encoder.|_libffmpeg_| diff --git a/buildffmpeg b/buildffmpeg index 857616b..11a81c6 100755 --- a/buildffmpeg +++ b/buildffmpeg @@ -112,7 +112,7 @@ else mkdir -p "${OUTDIR}" if [[ "$ONLY_ACTIVE_ARCH" == "YES" ]]; then if [[ "$NATIVE_ARCH" == "x86_64" ]]; then - compile "${OUTDIR}/${CONFIGURATION}/${NATIVE_ARCH}" "-mmacosx-version-min=10.15 -DNDEBUG" "" "" + compile "${OUTDIR}/${CONFIGURATION}/${NATIVE_ARCH}" "-mmacosx-version-min=10.14 -DNDEBUG" "" "" else compile "${OUTDIR}/${CONFIGURATION}/${NATIVE_ARCH}" "-target arm64-apple-macos11 -DNDEBUG" "-target arm64-apple-macos11" "arm" fi @@ -132,7 +132,7 @@ else exit $retVal fi else - compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.15 -DNDEBUG" "" "x86_64" + compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.14 -DNDEBUG" "" "x86_64" compile "${OUTDIR}/${CONFIGURATION}/arm64" "-target arm64-apple-macos11 -DNDEBUG" "-target arm64-apple-macos11" "arm64" diff --git a/buildwebp b/buildwebp index 6e7ebb2..9f02d18 100755 --- a/buildwebp +++ b/buildwebp @@ -104,7 +104,7 @@ else if [[ "$ONLY_ACTIVE_ARCH" == "YES" ]]; then if [[ "$NATIVE_ARCH" == "x86_64" ]]; then - compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.15 -DNDEBUG" "" "" + compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.14 -DNDEBUG" "" "" basename="${OUTDIR}/${CONFIGURATION}/x86_64/lib/" else @@ -121,7 +121,7 @@ else fi done else - compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.15 -DNDEBUG" "" "" + compile "${OUTDIR}/${CONFIGURATION}/x86_64" "-mmacosx-version-min=10.14 -DNDEBUG" "" "" compile "${OUTDIR}/${CONFIGURATION}/arm64" "-target arm64-apple-macos11 -DNDEBUG" "-target arm64-apple-macos11" "arm" diff --git a/docs/appcast.xml b/docs/appcast.xml index 8c66396..9226ee3 100644 --- a/docs/appcast.xml +++ b/docs/appcast.xml @@ -60,7 +60,7 @@ 1.5.3 lun, 31 Mag 2021 15:53:12 +0100 10.15 - +
  • Bugfix for chapters.
  • @@ -68,5 +68,19 @@ ]]>
    + + 1.5.4 + mar, 1 Giu 2021 19:16:12 +0100 + 10.14 + + +
  • Add info about number of audio channels.
  • +
  • Bugfix tracks (audio, video, subtitle) menu.
  • +
  • Experimental support for macOS 10.14.
  • + + ]]> +
    +