艦娘をちゅーちゅーします
修订版 | 65cb22fc7e490d1ecf9eca6840ebf9bce9868136 (tree) |
---|---|
时间 | 2017-08-08 21:29:39 |
作者 | masakih <masakih@user...> |
Commiter | masakih |
機能部分を分離
@@ -10,6 +10,7 @@ | ||
10 | 10 | F41A44C81F3710D10066F83D /* ProgressPanelController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41A44C61F3710D10066F83D /* ProgressPanelController.swift */; }; |
11 | 11 | F41A44C91F3710D10066F83D /* ProgressPanelController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F41A44C71F3710D10066F83D /* ProgressPanelController.xib */; }; |
12 | 12 | F41A44CE1F38B8510066F83D /* ApplicationDirecrories.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41A44CD1F38B8510066F83D /* ApplicationDirecrories.swift */; }; |
13 | + F41A44D21F39E1450066F83D /* ChuuChuu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41A44D11F39E1450066F83D /* ChuuChuu.swift */; }; | |
13 | 14 | F4EAFCBE1F369E71007B7506 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4EAFCBD1F369E71007B7506 /* AppDelegate.swift */; }; |
14 | 15 | F4EAFCC01F369E71007B7506 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4EAFCBF1F369E71007B7506 /* ViewController.swift */; }; |
15 | 16 | F4EAFCC21F369E71007B7506 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F4EAFCC11F369E71007B7506 /* Assets.xcassets */; }; |
@@ -41,6 +42,7 @@ | ||
41 | 42 | F41A44C61F3710D10066F83D /* ProgressPanelController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressPanelController.swift; sourceTree = "<group>"; }; |
42 | 43 | F41A44C71F3710D10066F83D /* ProgressPanelController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ProgressPanelController.xib; sourceTree = "<group>"; }; |
43 | 44 | F41A44CD1F38B8510066F83D /* ApplicationDirecrories.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationDirecrories.swift; sourceTree = "<group>"; }; |
45 | + F41A44D11F39E1450066F83D /* ChuuChuu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChuuChuu.swift; sourceTree = "<group>"; }; | |
44 | 46 | F4EAFCBA1F369E71007B7506 /* ExtractKanMusu.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ExtractKanMusu.app; sourceTree = BUILT_PRODUCTS_DIR; }; |
45 | 47 | F4EAFCBD1F369E71007B7506 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; |
46 | 48 | F4EAFCBF1F369E71007B7506 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; }; |
@@ -94,6 +96,7 @@ | ||
94 | 96 | F4EAFCBF1F369E71007B7506 /* ViewController.swift */, |
95 | 97 | F41A44C61F3710D10066F83D /* ProgressPanelController.swift */, |
96 | 98 | F41A44C71F3710D10066F83D /* ProgressPanelController.xib */, |
99 | + F41A44D11F39E1450066F83D /* ChuuChuu.swift */, | |
97 | 100 | F4EAFCCC1F36A28B007B7506 /* pickup.rb */, |
98 | 101 | F4EAFCCE1F36B8FE007B7506 /* PickUpSWF.swift */, |
99 | 102 | F4EAFCDF1F36D9E5007B7506 /* ExtractKanmusu.swift */, |
@@ -214,6 +217,7 @@ | ||
214 | 217 | F4EAFCC01F369E71007B7506 /* ViewController.swift in Sources */, |
215 | 218 | F4EAFCCF1F36B8FE007B7506 /* PickUpSWF.swift in Sources */, |
216 | 219 | F4EAFCE01F36D9E5007B7506 /* ExtractKanmusu.swift in Sources */, |
220 | + F41A44D21F39E1450066F83D /* ChuuChuu.swift in Sources */, | |
217 | 221 | F4EAFCBE1F369E71007B7506 /* AppDelegate.swift in Sources */, |
218 | 222 | F41A44C81F3710D10066F83D /* ProgressPanelController.swift in Sources */, |
219 | 223 | ); |
@@ -10,9 +10,7 @@ import Cocoa | ||
10 | 10 | |
11 | 11 | @NSApplicationMain |
12 | 12 | class AppDelegate: NSObject, NSApplicationDelegate { |
13 | - | |
14 | - | |
15 | - | |
13 | + | |
16 | 14 | func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool { |
17 | 15 | |
18 | 16 | return true |
@@ -0,0 +1,185 @@ | ||
1 | +// | |
2 | +// ChuuChuu.swift | |
3 | +// ExtractKanMusu | |
4 | +// | |
5 | +// Created by Hori,Masaki on 2017/08/08. | |
6 | +// Copyright © 2017年 Hori,Masaki. All rights reserved. | |
7 | +// | |
8 | + | |
9 | +import Foundation | |
10 | + | |
11 | + | |
12 | +protocol MessageObserver: class { | |
13 | + | |
14 | + var message: String { get set } | |
15 | + | |
16 | + var count: Int { get set } | |
17 | + | |
18 | + func increse() | |
19 | +} | |
20 | + | |
21 | +class ChuuChuu { | |
22 | + | |
23 | + static let chuchu = "ちゅーちゅー" | |
24 | + static let tempDirName = "___temp_chu-chu-_ship___" | |
25 | + | |
26 | + let observer: MessageObserver | |
27 | + let originalDir: URL | |
28 | + let destinationDir: URL | |
29 | + | |
30 | + private var maxPower = false | |
31 | + private var useCoreCount: Int { | |
32 | + | |
33 | + let coreCount = ProcessInfo.processInfo.processorCount | |
34 | + | |
35 | + return maxPower ? coreCount : coreCount / 2 | |
36 | + } | |
37 | + | |
38 | + init(observer: MessageObserver, original: URL, destination: URL) { | |
39 | + | |
40 | + self.observer = observer | |
41 | + originalDir = original | |
42 | + destinationDir = destination | |
43 | + } | |
44 | + | |
45 | + | |
46 | + private func createTempDir() throws { | |
47 | + | |
48 | + let tempURL = originalDir.appendingPathComponent(ChuuChuu.tempDirName) | |
49 | + | |
50 | + try FileManager.default | |
51 | + .createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) | |
52 | + | |
53 | + } | |
54 | + | |
55 | + private func deleteTempDir() throws { | |
56 | + | |
57 | + let tempURL = originalDir.appendingPathComponent(ChuuChuu.tempDirName) | |
58 | + | |
59 | + try FileManager.default.removeItem(at: tempURL) | |
60 | + } | |
61 | + | |
62 | + private func createDestDir() throws { | |
63 | + | |
64 | + let destURL = destinationDir.appendingPathComponent(ChuuChuu.chuchu) | |
65 | + | |
66 | + try FileManager.default | |
67 | + .createDirectory(at: destURL, withIntermediateDirectories: true, attributes: nil) | |
68 | + | |
69 | + } | |
70 | + | |
71 | + private func moveSWF(from originalDir: URL, to destinationDir: URL) { | |
72 | + | |
73 | + observer.message = "Picking up SWF file from Cache Directory." | |
74 | + | |
75 | + do { | |
76 | + | |
77 | + try pickUpSWF(from: originalDir, to: destinationDir) | |
78 | + | |
79 | + } catch { | |
80 | + | |
81 | + print("Can not pickup.", terminator: " : ") | |
82 | + | |
83 | + guard let error = error as? PickUPSWFError else { | |
84 | + | |
85 | + print("Unkown error.") | |
86 | + return | |
87 | + } | |
88 | + | |
89 | + switch error { | |
90 | + case .scriptNotFound: print("Script not found.") | |
91 | + | |
92 | + case let .commandFail(status): print("Command faile status \(status).") | |
93 | + } | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + private func extractKanmusus(swfs: [URL], to destURL: URL) { | |
98 | + | |
99 | + observer.message = "Extracting KanMusu Image from SWF file." | |
100 | + | |
101 | + let semaphone = DispatchSemaphore(value: useCoreCount) | |
102 | + let group = DispatchGroup() | |
103 | + let queue = DispatchQueue(label: "extract", attributes: .concurrent) | |
104 | + | |
105 | + swfs.forEach { swf in | |
106 | + | |
107 | + queue.async(group: group) { | |
108 | + | |
109 | + semaphone.wait() | |
110 | + | |
111 | + do { | |
112 | + | |
113 | + try extractKanmusu(swf: swf, to: destURL) | |
114 | + | |
115 | + } catch { | |
116 | + | |
117 | + print(error) | |
118 | + } | |
119 | + | |
120 | + semaphone.signal() | |
121 | + | |
122 | + self.observer.increse() | |
123 | + | |
124 | + } | |
125 | + | |
126 | + } | |
127 | + | |
128 | + group.wait() | |
129 | + } | |
130 | + | |
131 | + | |
132 | + func execute(maxPower: Bool, completeHandler: @escaping () -> Void) { | |
133 | + | |
134 | + guard let existOriginalDir = try? originalDir.checkResourceIsReachable(), | |
135 | + existOriginalDir else { | |
136 | + | |
137 | + completeHandler() | |
138 | + return | |
139 | + } | |
140 | + | |
141 | + guard let existDestinationDir = try? destinationDir.checkResourceIsReachable(), | |
142 | + existDestinationDir else { | |
143 | + | |
144 | + completeHandler() | |
145 | + return | |
146 | + } | |
147 | + | |
148 | + self.maxPower = maxPower | |
149 | + | |
150 | + | |
151 | + DispatchQueue(label: "Nya-nn").async { | |
152 | + | |
153 | + do { | |
154 | + | |
155 | + try self.createTempDir() | |
156 | + try self.createDestDir() | |
157 | + | |
158 | + self.moveSWF(from: self.originalDir, to: self.destinationDir) | |
159 | + | |
160 | + let tempURL = self.originalDir.appendingPathComponent(ChuuChuu.tempDirName) | |
161 | + let destURL = self.destinationDir.appendingPathComponent(ChuuChuu.chuchu) | |
162 | + | |
163 | + let swfs = try FileManager.default | |
164 | + .contentsOfDirectory(at: tempURL, includingPropertiesForKeys: nil) | |
165 | + .filter { $0.pathExtension.lowercased() == "swf" } | |
166 | + | |
167 | + self.observer.count = swfs.count | |
168 | + | |
169 | + self.extractKanmusus(swfs: swfs, to: destURL) | |
170 | + | |
171 | + try self.deleteTempDir() | |
172 | + | |
173 | + } catch { | |
174 | + | |
175 | + print(error) | |
176 | + } | |
177 | + | |
178 | + DispatchQueue.main.async { | |
179 | + | |
180 | + completeHandler() | |
181 | + } | |
182 | + } | |
183 | + } | |
184 | + | |
185 | +} |
@@ -8,7 +8,7 @@ | ||
8 | 8 | |
9 | 9 | import Cocoa |
10 | 10 | |
11 | -class ProgressPanelController: NSWindowController { | |
11 | +class ProgressPanelController: NSWindowController, MessageObserver { | |
12 | 12 | |
13 | 13 | private dynamic var rawCount: Int = 0 { |
14 | 14 |
@@ -83,7 +83,7 @@ class ProgressPanelController: NSWindowController { | ||
83 | 83 | return "ProgressPanelController" |
84 | 84 | } |
85 | 85 | |
86 | - func appendFinished() { | |
86 | + func increse() { | |
87 | 87 | |
88 | 88 | DispatchQueue.main.async { |
89 | 89 |
@@ -10,25 +10,16 @@ import Cocoa | ||
10 | 10 | |
11 | 11 | class ViewController: NSViewController { |
12 | 12 | |
13 | - static let chuchu = "ちゅーちゅー" | |
14 | - static let tempDirName = "___temp_chu-chu-_ship___" | |
15 | - | |
16 | - | |
17 | 13 | let progress = ProgressPanelController() |
18 | 14 | |
15 | + var chuuchuu: ChuuChuu? | |
16 | + | |
19 | 17 | |
20 | 18 | @IBOutlet var cachePathField: NSPathControl! |
21 | 19 | @IBOutlet var outputFolderField: NSPathControl! |
22 | 20 | |
23 | 21 | dynamic var maxPower = false |
24 | 22 | |
25 | - var useCoreCount: Int { | |
26 | - | |
27 | - let coreCount = ProcessInfo.processInfo.processorCount | |
28 | - | |
29 | - return maxPower ? coreCount : coreCount / 2 | |
30 | - } | |
31 | - | |
32 | 23 | |
33 | 24 | override func viewDidLoad() { |
34 | 25 |
@@ -63,8 +54,7 @@ extension ViewController { | ||
63 | 54 | |
64 | 55 | panel.beginSheetModal(for: window) { |
65 | 56 | |
66 | - guard $0 == NSFileHandlingPanelOKButton | |
67 | - else { return } | |
57 | + guard $0 == NSFileHandlingPanelOKButton else { return } | |
68 | 58 | |
69 | 59 | handler(panel.url) |
70 | 60 |
@@ -95,177 +85,30 @@ extension ViewController { | ||
95 | 85 | |
96 | 86 | @IBAction func extract(_ : Any?) { |
97 | 87 | |
98 | - self.view.window?.beginSheet(progress.window!, completionHandler: nil) | |
99 | - | |
100 | - execute() { [weak self] in | |
88 | + guard let original = cachePathField.url else { | |
101 | 89 | |
102 | - guard let `self` = self else { return } | |
103 | - | |
104 | - self.view.window?.endSheet(self.progress.window!) | |
105 | - } | |
106 | - | |
107 | - } | |
108 | -} | |
109 | - | |
110 | -extension ViewController { | |
111 | - | |
112 | - private enum ExtractKanMusu: Error { | |
113 | - | |
114 | - case urlMissing(String) | |
115 | - } | |
116 | - private func createTempDir() throws { | |
117 | - | |
118 | - guard let tempParentURL = cachePathField.url else { | |
119 | - | |
120 | - throw ExtractKanMusu.urlMissing("Cache dir is nil") | |
121 | - } | |
122 | - | |
123 | - let tempURL = tempParentURL.appendingPathComponent(ViewController.tempDirName) | |
124 | - | |
125 | - try FileManager.default | |
126 | - .createDirectory(at: tempURL, withIntermediateDirectories: true, attributes: nil) | |
127 | - | |
128 | - } | |
129 | - | |
130 | - private func deleteTempDir() throws { | |
131 | - | |
132 | - guard let tempParentURL = cachePathField.url else { | |
133 | - | |
134 | - throw ExtractKanMusu.urlMissing("Cache dir is nil") | |
135 | - } | |
136 | - | |
137 | - let tempURL = tempParentURL.appendingPathComponent(ViewController.tempDirName) | |
138 | - | |
139 | - try FileManager.default.removeItem(at: tempURL) | |
140 | - } | |
141 | - | |
142 | - private func createDestDir() throws { | |
143 | - | |
144 | - guard let destParentURL = outputFolderField.url else { | |
90 | + print("CachPath is nil.") | |
145 | 91 | |
146 | - throw ExtractKanMusu.urlMissing("Output dir is nil") | |
92 | + return | |
147 | 93 | } |
148 | 94 | |
149 | - let destURL = destParentURL.appendingPathComponent(ViewController.chuchu) | |
150 | - | |
151 | - try FileManager.default | |
152 | - .createDirectory(at: destURL, withIntermediateDirectories: true, attributes: nil) | |
153 | - | |
154 | - } | |
155 | - | |
156 | - private func moveSWF(from originalDir: URL, to destinationDir: URL) { | |
157 | - | |
158 | - progress.message = "Picking up SWF file from Cache Directory." | |
159 | - | |
160 | - do { | |
161 | - | |
162 | - try pickUpSWF(from: originalDir, to: destinationDir) | |
163 | - | |
164 | - } catch { | |
165 | - | |
166 | - print("Can not pickup.", terminator: " : ") | |
95 | + guard let dest = outputFolderField.url else { | |
167 | 96 | |
168 | - guard let error = error as? PickUPSWFError else { | |
169 | - print("Unkown error.") | |
170 | - return | |
171 | - } | |
97 | + print("outputPath is nil.") | |
172 | 98 | |
173 | - switch error { | |
174 | - case .scriptNotFound: print("Script not found.") | |
175 | - | |
176 | - case let .commandFail(status): print("Command faile status \(status).") | |
177 | - } | |
99 | + return | |
178 | 100 | } |
179 | - } | |
180 | - | |
181 | - | |
182 | - private func extractKanmusus(swfs: [URL], to destURL: URL) { | |
183 | 101 | |
184 | - progress.message = "Extracting KanMusu Image from SWF file." | |
102 | + chuuchuu = ChuuChuu(observer: progress, original: original, destination: dest) | |
185 | 103 | |
186 | - let semaphone = DispatchSemaphore(value: useCoreCount) | |
187 | - let group = DispatchGroup() | |
188 | - let queue = DispatchQueue(label: "extract", attributes: .concurrent) | |
104 | + self.view.window?.beginSheet(progress.window!, completionHandler: nil) | |
189 | 105 | |
190 | - swfs.forEach { swf in | |
106 | + chuuchuu?.execute(maxPower: maxPower) { [weak self] in | |
191 | 107 | |
192 | - queue.async(group: group) { | |
193 | - | |
194 | - semaphone.wait() | |
195 | - | |
196 | - do { | |
197 | - | |
198 | - try extractKanmusu(swf: swf, to: destURL) | |
199 | - | |
200 | - } catch { | |
201 | - | |
202 | - print(error) | |
203 | - } | |
204 | - | |
205 | - semaphone.signal() | |
206 | - | |
207 | - self.progress.appendFinished() | |
208 | - | |
209 | - } | |
108 | + guard let `self` = self else { return } | |
210 | 109 | |
110 | + self.view.window?.endSheet(self.progress.window!) | |
211 | 111 | } |
212 | 112 | |
213 | - group.wait() | |
214 | - } | |
215 | - | |
216 | - | |
217 | - fileprivate func execute(completeHandler: @escaping () -> Void) { | |
218 | - | |
219 | - guard let originalDir = cachePathField.url, | |
220 | - let existOriginalDir = try? originalDir.checkResourceIsReachable(), | |
221 | - existOriginalDir else { | |
222 | - | |
223 | - completeHandler() | |
224 | - return | |
225 | - } | |
226 | - | |
227 | - guard let destinationDir = outputFolderField.url, | |
228 | - let existDestinationDir = try? destinationDir.checkResourceIsReachable(), | |
229 | - existDestinationDir else { | |
230 | - | |
231 | - completeHandler() | |
232 | - return | |
233 | - } | |
234 | - | |
235 | - | |
236 | - DispatchQueue(label: "Nya-nn").async { | |
237 | - | |
238 | - do { | |
239 | - | |
240 | - try self.createTempDir() | |
241 | - try self.createDestDir() | |
242 | - | |
243 | - self.moveSWF(from: originalDir, to: destinationDir) | |
244 | - | |
245 | - let tempURL = originalDir.appendingPathComponent(ViewController.tempDirName) | |
246 | - let destURL = destinationDir.appendingPathComponent(ViewController.chuchu) | |
247 | - | |
248 | - let swfs = try FileManager.default | |
249 | - .contentsOfDirectory(at: tempURL, includingPropertiesForKeys: nil) | |
250 | - .filter { $0.pathExtension.lowercased() == "swf" } | |
251 | - | |
252 | - self.progress.count = swfs.count | |
253 | - | |
254 | - self.extractKanmusus(swfs: swfs, to: destURL) | |
255 | - | |
256 | - try self.deleteTempDir() | |
257 | - | |
258 | - } catch { | |
259 | - | |
260 | - print(error) | |
261 | - } | |
262 | - | |
263 | - DispatchQueue.main.async { | |
264 | - | |
265 | - completeHandler() | |
266 | - } | |
267 | - } | |
268 | 113 | } |
269 | - | |
270 | 114 | } |
271 | - |