Skip to content
This repository was archived by the owner on Aug 11, 2024. It is now read-only.

Commit 2509eb4

Browse files
Compress image assets and support XML export for VMware Fusion users.
1 parent 8fa97ed commit 2509eb4

File tree

59 files changed

+938
-22
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+938
-22
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,22 @@ After successfully modifying or installing the app, you can play with it to your
109109

110110
---
111111

112+
### Workaround to install Final Cut Pro 7 in VMware Fusion
113+
114+
If you don't have a Mac released before Late 2019, you can still install Final Cut Pro 7 in VMware Fusion to export existing Final Cut Pro 7 projects into XML files. This lets SendToX, DaVinci Resolve, Media Composer, and Premiere Pro open them.
115+
116+
- [Install macOS Mojave virtual machine with VMware Fusion](https://www.huibdijkstra.nl/how-to-set-up-a-osx-mojave-vm-in-vmware-fusion/). Other virtual machine software, such as Parallels Desktop, is not supported and will not work.
117+
- After mounting the Final Cut Studio installer in VMware Fusion, right click on Install Final Cut Studio.pkg > Show Original, then copy FinalCutStudio.mpkg and Packages to VMware Fusion's Desktop
118+
- Right click on the copied FinalCutStudio.mpkg > Show Package Contents > Resources
119+
- Right click on Requirements Checker.app > Show Package Contents > Contents > Resources
120+
- Delete minsys.plist
121+
- Double click on the modified FinalCutStudio.mpkg to start the install
122+
- Use Retroactive as usual
123+
124+
To use editing features such as timeline and preview, install macOS Mojave on a real, older Mac released before Late 2019, then run Retroactive as usual.
125+
126+
---
127+
112128
### Last words
113129
- If GateKeeper prevents you from running modified versions of your chosen app, [temporarily disable GateKeeper in Terminal with `sudo spctl --master-disable`](http://osxdaily.com/2015/05/04/disable-gatekeeper-command-line-mac-osx/).
114130

Retroactive.xcodeproj/project.pbxproj

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
606CA155236666B3001C550E /* ConfettiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 606CA151236666B3001C550E /* ConfettiView.swift */; };
6161
607C3D822382665900FAE528 /* AudioToolbox.framework.zip in Resources */ = {isa = PBXBuildFile; fileRef = 607C3D812382665900FAE528 /* AudioToolbox.framework.zip */; };
6262
60A58ABF2366318D00FFC1A3 /* SupportPath.plist in Resources */ = {isa = PBXBuildFile; fileRef = 32F763432364C8C000200ED7 /* SupportPath.plist */; };
63+
60D728A023D5787B0006F233 /* VMFCPFixerScript in Resources */ = {isa = PBXBuildFile; fileRef = 60D7289F23D5787B0006F233 /* VMFCPFixerScript */; };
6364
/* End PBXBuildFile section */
6465

6566
/* Begin PBXFileReference section */
@@ -129,6 +130,7 @@
129130
607C3D7F2382409B00FAE528 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
130131
607C3D802382409B00FAE528 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
131132
607C3D812382665900FAE528 /* AudioToolbox.framework.zip */ = {isa = PBXFileReference; lastKnownFileType = archive.zip; path = AudioToolbox.framework.zip; sourceTree = "<group>"; };
133+
60D7289F23D5787B0006F233 /* VMFCPFixerScript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = VMFCPFixerScript; sourceTree = "<group>"; };
132134
/* End PBXFileReference section */
133135

134136
/* Begin PBXFrameworksBuildPhase section */
@@ -214,6 +216,7 @@
214216
606CA12023664BFC001C550E /* killpkg */,
215217
046034E32381B6E800070C86 /* KeynoteScript */,
216218
042E9E472381AC2B001D3F38 /* GeneralFixerScript */,
219+
60D7289F23D5787B0006F233 /* VMFCPFixerScript */,
217220
607C3D812382665900FAE528 /* AudioToolbox.framework.zip */,
218221
046034E52381C18900070C86 /* BrowserKit.framework.zip */,
219222
046034E62381C18A00070C86 /* ProKit.framework.zip */,
@@ -386,6 +389,7 @@
386389
606CA154236666B3001C550E /* ConfettiView.bundle in Resources */,
387390
046034E72381C18A00070C86 /* BrowserKit.framework.zip in Resources */,
388391
046034EA2381DDB300070C86 /* ProApplicationsUpdate2010-02.dist in Resources */,
392+
60D728A023D5787B0006F233 /* VMFCPFixerScript in Resources */,
389393
042E9E4B2381AC2C001D3F38 /* GeneralFixerScript in Resources */,
390394
32F763462364C9F800200ED7 /* insert_dylib in Resources */,
391395
607C3D822382665900FAE528 /* AudioToolbox.framework.zip in Resources */,
@@ -602,7 +606,7 @@
602606
CODE_SIGN_ENTITLEMENTS = Retroactive/Support/Retroactive.entitlements;
603607
CODE_SIGN_STYLE = Automatic;
604608
COMBINE_HIDPI_IMAGES = YES;
605-
CURRENT_PROJECT_VERSION = 16;
609+
CURRENT_PROJECT_VERSION = 21;
606610
INFOPLIST_FILE = Retroactive/Support/Info.plist;
607611
LD_RUNPATH_SEARCH_PATHS = (
608612
"$(inherited)",
@@ -623,7 +627,7 @@
623627
CODE_SIGN_ENTITLEMENTS = Retroactive/Support/Retroactive.entitlements;
624628
CODE_SIGN_STYLE = Automatic;
625629
COMBINE_HIDPI_IMAGES = YES;
626-
CURRENT_PROJECT_VERSION = 16;
630+
CURRENT_PROJECT_VERSION = 21;
627631
INFOPLIST_FILE = Retroactive/Support/Info.plist;
628632
LD_RUNPATH_SEARCH_PATHS = (
629633
"$(inherited)",

Retroactive/AppManager.swift

Lines changed: 241 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ enum iTunesVersion {
2222
case coverFlow
2323
}
2424

25+
enum VirtualMachine {
26+
case parallels
27+
case vmware
28+
case generic
29+
}
30+
2531
let kCFBundleIdentifier = "CFBundleIdentifier"
2632
let kCFBundleVersion = "CFBundleVersion"
2733
let kCFBundleShortVersionString = "CFBundleShortVersionString"
@@ -36,6 +42,8 @@ let actionPresentTenseToken = "{actionPR}"
3642

3743
let kCustomSettingsPath = "/Library/Application Support/Final Cut Pro System Support/Custom Settings"
3844

45+
let lastHWForMojave = ["iMac19,2", "iMacPro1,1", "MacBook10,1", "MacBookAir8,2", "MacBookPro15,4", "Macmini8,1", "MacPro6,1"]
46+
3947
extension Bundle {
4048
var cfBundleVersionInt: Int? {
4149
get {
@@ -65,6 +73,57 @@ extension NSObject {
6573
}
6674
}
6775

76+
extension String {
77+
var machineType: String? {
78+
return self.components(separatedBy: .decimalDigits).first
79+
}
80+
81+
var machineFullNumber: String? {
82+
if let modelType = self.machineType {
83+
return self.replacingOccurrences(of: modelType, with: "")
84+
}
85+
return nil
86+
}
87+
88+
var machineGenerationNumber: Int? {
89+
if let fullNumber = self.machineFullNumber {
90+
let seperated = fullNumber.components(separatedBy: ",")
91+
if seperated.count > 1 {
92+
if let intGen = Int(seperated[0]) {
93+
return intGen
94+
}
95+
}
96+
}
97+
return nil
98+
}
99+
100+
var machineSubmodelNumber: Int? {
101+
if let fullNumber = self.machineFullNumber {
102+
let seperated = fullNumber.components(separatedBy: ",")
103+
if seperated.count > 1 {
104+
if let intSub = Int(seperated[1]) {
105+
return intSub
106+
}
107+
}
108+
}
109+
return nil
110+
}
111+
112+
func isNewerThan(otherMachine: String) -> Bool {
113+
if (self.machineType == otherMachine.machineType) {
114+
if let thisGen = self.machineGenerationNumber, let thisSub = self.machineSubmodelNumber, let otherGen = otherMachine.machineGenerationNumber, let otherSub = otherMachine.machineSubmodelNumber {
115+
if thisGen > otherGen {
116+
return true
117+
}
118+
if thisGen == otherGen && thisSub > otherSub {
119+
return true
120+
}
121+
}
122+
}
123+
return false
124+
}
125+
}
126+
68127
class AppManager: NSObject {
69128

70129
static let shared = AppManager()
@@ -514,7 +573,13 @@ class AppManager: NSObject {
514573
case .itunes:
515574
fatalError()
516575
case .finalCutPro7:
517-
return "GeneralFixerScript"
576+
if self.likelyInVirtualMachine {
577+
print("In VM and FCP7, using VM fixer script")
578+
return "VMFCPFixerScript"
579+
} else {
580+
print("Normal FCP7, using general fixer script")
581+
return "GeneralFixerScript"
582+
}
518583
case .logicPro9:
519584
return "GeneralFixerScript"
520585
case .keynote5:
@@ -907,5 +972,180 @@ class AppManager: NSObject {
907972
.replacingOccurrences(of: actionDetailToken, with: AppManager.shared.detailActionOfChosenApp)
908973
.replacingOccurrences(of: systemNameToken, with: ProcessInfo.versionName)
909974
}
975+
976+
var platform: String {
977+
get {
978+
var size = 0
979+
sysctlbyname("hw.model", nil, &size, nil, 0)
980+
var machine = [CChar](repeating: 0, count: size)
981+
sysctlbyname("hw.model", &machine, &size, nil, 0)
982+
return String(cString: machine)
983+
}
984+
}
985+
986+
var platformShippedAfterMojave: Bool {
987+
let hwIdentifier = self.platform
988+
var machineTypeMatchedAtLeastOnce = false
989+
for mac in lastHWForMojave {
990+
if hwIdentifier.isNewerThan(otherMachine: mac) {
991+
return true
992+
}
993+
if hwIdentifier.machineType == mac.machineType {
994+
machineTypeMatchedAtLeastOnce = true
995+
}
996+
}
997+
return !machineTypeMatchedAtLeastOnce
998+
}
999+
1000+
var chosenAppHasLimitedFeaturesInVirtualMachine: Bool {
1001+
get {
1002+
switch self.chosenApp {
1003+
case .aperture:
1004+
return true
1005+
case .iphoto:
1006+
return true
1007+
case .proVideoUpdate:
1008+
fallthrough
1009+
case .finalCutPro7:
1010+
return true
1011+
case .keynote5:
1012+
return true
1013+
case .logicPro9:
1014+
return false
1015+
case .itunes:
1016+
return false
1017+
default:
1018+
return false
1019+
}
1020+
}
1021+
}
1022+
1023+
var currentVM: VirtualMachine {
1024+
let platform = self.platform
1025+
if (platform.contains("VMware")) {
1026+
return .vmware
1027+
}
1028+
if (platform.contains("Parallels")) {
1029+
return .parallels
1030+
}
1031+
return .generic
1032+
}
1033+
1034+
var currentVMName: String {
1035+
switch self.currentVM {
1036+
case .vmware:
1037+
return "VMware Fusion".localized()
1038+
case .parallels:
1039+
return "Parallels Desktop".localized()
1040+
case .generic:
1041+
fallthrough
1042+
default:
1043+
return "a virtual machine".localized()
1044+
}
1045+
}
1046+
1047+
var currentVMImage: NSImage? {
1048+
switch self.currentVM {
1049+
case .vmware:
1050+
return NSImage(named: "vmware")
1051+
case .parallels:
1052+
return NSImage(named: "parallels")
1053+
case .generic:
1054+
fallthrough
1055+
default:
1056+
return NSImage(named: "generic-vm")
1057+
}
1058+
}
1059+
1060+
var chosenAppVMTitle: String {
1061+
get {
1062+
let basicFormat = "%1$@ in %2$@".localized()
1063+
switch self.chosenApp {
1064+
case .aperture:
1065+
return String(format: basicFormat, "Aperture has reduced functionality".localized(), self.currentVMName)
1066+
case .iphoto:
1067+
return String(format: basicFormat, "iPhoto has reduced functionality".localized(), self.currentVMName)
1068+
case .proVideoUpdate:
1069+
fallthrough
1070+
case .finalCutPro7:
1071+
return String(format: basicFormat, "Final Cut Pro 7 only supports XML exports".localized(), self.currentVMName)
1072+
case .keynote5:
1073+
return String(format: basicFormat, "Keynote ’09 only supports PPTX exports".localized(), self.currentVMName)
1074+
case .logicPro9:
1075+
return ""
1076+
case .itunes:
1077+
return ""
1078+
default:
1079+
return ""
1080+
}
1081+
}
1082+
}
1083+
1084+
var chosenAppVMDescription: String {
1085+
get {
1086+
switch self.chosenApp {
1087+
case .aperture:
1088+
return "You can open and organize your Aperture library, or export edited images. To use editing features such as image preview, adjustments, brushes, and effects, run Retroactive on a real Mac.".localized()
1089+
case .iphoto:
1090+
return "You can open and organize your iPhoto library, or export edited images. To use editing features such as image preview, Quick Fixes, effects, and adjustments, run Retroactive on a real Mac.".localized()
1091+
case .proVideoUpdate:
1092+
fallthrough
1093+
case .finalCutPro7:
1094+
return "You can export existing projects into XML files, so that SendToX, DaVinci Resolve, Media Composer, and Premiere Pro can open them. To use editing features such as timeline and preview, run Retroactive on a real Mac.".localized()
1095+
case .keynote5:
1096+
return "You can export existing Keynote presentations into PowerPoint presentations. To view and edit your Keynote slides, animations, and transitions, run Retroactive on a real Mac.".localized()
1097+
case .logicPro9:
1098+
return ""
1099+
case .itunes:
1100+
return ""
1101+
default:
1102+
return ""
1103+
}
1104+
}
1105+
}
9101106

1107+
private var _previouslyDetectedInVM: Bool = false
1108+
1109+
var likelyInVirtualMachine: Bool {
1110+
get {
1111+
if _previouslyDetectedInVM == true {
1112+
print("previously already detected in VM, skipping the check")
1113+
return true
1114+
}
1115+
print("main window is \(String(describing: NSApp.mainWindow)), screen is \(String(describing: NSApp.mainWindow?.screen))")
1116+
var window = NSApp.mainWindow
1117+
if (window == nil) {
1118+
let subwindows = NSApp.windows
1119+
print("main window is nil, NSApp.windows are \(subwindows)")
1120+
for subwindow in subwindows {
1121+
if let validWindow = subwindow as? RetroactiveWindow {
1122+
window = validWindow
1123+
}
1124+
}
1125+
if (window == nil && subwindows.count > 0) {
1126+
window = subwindows[0]
1127+
}
1128+
}
1129+
let deviceDescription = window?.screen?.deviceDescription
1130+
print("device description is \(String(describing: deviceDescription))")
1131+
if let description = deviceDescription {
1132+
print("screen number is \(String(describing: description[NSDeviceDescriptionKey("NSScreenNumber")]))")
1133+
if let screenNumber = description[NSDeviceDescriptionKey("NSScreenNumber")] as? CGDirectDisplayID {
1134+
let usesOpenGL = CGDisplayUsesOpenGLAcceleration(screenNumber)
1135+
print("usesOpenGL is \(usesOpenGL)")
1136+
if CGDisplayUsesOpenGLAcceleration(screenNumber) == 1 {
1137+
print("OpenGL acceleration present, likely not in virtual machine")
1138+
return false
1139+
} else {
1140+
print("OpenGL acceleration missing, likely in virtual machine")
1141+
_previouslyDetectedInVM = true
1142+
return true
1143+
}
1144+
}
1145+
}
1146+
print("can't find current screen, assuming not in virtual machine")
1147+
return false
1148+
}
1149+
}
1150+
9111151
}

0 commit comments

Comments
 (0)