• R/O
  • HTTP
  • SSH
  • HTTPS

main: Commit

Elis ColorsのMainリポジトリ。


Commit MetaInfo

Revision13de7fc49589fa9ccea8f72b6c2ab5e4c8c9a579 (tree)
Time2009-09-24 23:28:08
AuthorYanagi Asakura <yanagi.entertainment@gmai...>
CommiterYanagi Asakura

Log Message

add undo/redo system

Change Summary

Incremental Difference

--- a/Elis Colors.xcodeproj/project.pbxproj
+++ b/Elis Colors.xcodeproj/project.pbxproj
@@ -10,12 +10,14 @@
1010 1DDD58160DA1D0A300B32029 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1DDD58140DA1D0A300B32029 /* MainMenu.xib */; };
1111 256AC3DA0F4B6AC300CF3369 /* Elis_ColorsAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 256AC3D90F4B6AC300CF3369 /* Elis_ColorsAppDelegate.m */; };
1212 5C01A8C11064ACFB0076B735 /* MainMenuForSmallDisplay.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5C01A8BF1064ACFB0076B735 /* MainMenuForSmallDisplay.xib */; };
13+ 5C0DDDC5106B5652008425EE /* ElisUndoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C0DDDC4106B5652008425EE /* ElisUndoManager.m */; };
1314 5C56077F105FB3B70094F837 /* ElisPropertyTableController.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C56077E105FB3B70094F837 /* ElisPropertyTableController.m */; };
1415 5C560820105FCA140094F837 /* ElisCoreImageKernel.cikernel in Sources */ = {isa = PBXBuildFile; fileRef = 5C56081D105FCA140094F837 /* ElisCoreImageKernel.cikernel */; };
1516 5C560821105FCA140094F837 /* ElisCustomFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C56081F105FCA140094F837 /* ElisCustomFilter.m */; };
1617 5C808D6A105CDA6800818B1A /* ElisCustomCALayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C808D69105CDA6800818B1A /* ElisCustomCALayer.m */; };
1718 5C808EAC105CEDCB00818B1A /* white.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5C808EAB105CEDCB00818B1A /* white.jpg */; };
1819 5C808EC5105CEE6E00818B1A /* trackgray.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5C808EC4105CEE6E00818B1A /* trackgray.jpg */; };
20+ 5C8A4811106A66ED00EC2F3D /* ElisWriterLegacy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C8A4810106A66ED00EC2F3D /* ElisWriterLegacy.m */; };
1921 5C9F358B105F7BEA00D87A46 /* ElisEffect.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9F358A105F7BEA00D87A46 /* ElisEffect.m */; };
2022 5C9F358E105F7C0F00D87A46 /* ElisKeyframe.m in Sources */ = {isa = PBXBuildFile; fileRef = 5C9F358D105F7C0F00D87A46 /* ElisKeyframe.m */; };
2123 5CB6798C10637CA400FC5F9F /* lightgreen.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 5CB6798A10637CA400FC5F9F /* lightgreen.jpg */; };
@@ -53,6 +55,8 @@
5355 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = "<absolute>"; };
5456 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
5557 5C01A8C01064ACFB0076B735 /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = English.lproj/MainMenuForSmallDisplay.xib; sourceTree = "<group>"; };
58+ 5C0DDDC3106B5652008425EE /* ElisUndoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElisUndoManager.h; sourceTree = "<group>"; };
59+ 5C0DDDC4106B5652008425EE /* ElisUndoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ElisUndoManager.m; sourceTree = "<group>"; };
5660 5C56077D105FB3B70094F837 /* ElisPropertyTableController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElisPropertyTableController.h; sourceTree = "<group>"; };
5761 5C56077E105FB3B70094F837 /* ElisPropertyTableController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ElisPropertyTableController.m; sourceTree = "<group>"; };
5862 5C56081D105FCA140094F837 /* ElisCoreImageKernel.cikernel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.glsl; name = ElisCoreImageKernel.cikernel; path = ../Elis/ElisCoreImageKernel.cikernel; sourceTree = SOURCE_ROOT; };
@@ -62,6 +66,8 @@
6266 5C808D69105CDA6800818B1A /* ElisCustomCALayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ElisCustomCALayer.m; sourceTree = "<group>"; };
6367 5C808EAB105CEDCB00818B1A /* white.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = white.jpg; path = ../Elis/image/white.jpg; sourceTree = SOURCE_ROOT; };
6468 5C808EC4105CEE6E00818B1A /* trackgray.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = trackgray.jpg; path = ../Elis/image/trackgray.jpg; sourceTree = SOURCE_ROOT; };
69+ 5C8A480F106A66ED00EC2F3D /* ElisWriterLegacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElisWriterLegacy.h; sourceTree = "<group>"; };
70+ 5C8A4810106A66ED00EC2F3D /* ElisWriterLegacy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ElisWriterLegacy.m; sourceTree = "<group>"; };
6571 5C9F3589105F7BEA00D87A46 /* ElisEffect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElisEffect.h; sourceTree = "<group>"; };
6672 5C9F358A105F7BEA00D87A46 /* ElisEffect.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ElisEffect.m; sourceTree = "<group>"; };
6773 5C9F358C105F7C0F00D87A46 /* ElisKeyframe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElisKeyframe.h; sourceTree = "<group>"; };
@@ -134,10 +140,8 @@
134140 5C9F358A105F7BEA00D87A46 /* ElisEffect.m */,
135141 5C9F358C105F7C0F00D87A46 /* ElisKeyframe.h */,
136142 5C9F358D105F7C0F00D87A46 /* ElisKeyframe.m */,
137- 5CE26AD5105BD8B50082C63A /* ElisAnimationLayerFactory.h */,
138- 5CE26AD6105BD8B50082C63A /* ElisAnimationLayerFactory.m */,
139- 5C808D68105CDA6800818B1A /* ElisCustomCALayer.h */,
140- 5C808D69105CDA6800818B1A /* ElisCustomCALayer.m */,
143+ 5C0DDF01106BB945008425EE /* Animation Layer */,
144+ 5C0DDDC2106B563A008425EE /* Undo Manager */,
141145 5CF28E0A1062580F00C49262 /* Writer */,
142146 5CE26955105B86710082C63A /* Property Table */,
143147 5CE26942105B81D60082C63A /* TimeLine */,
@@ -225,6 +229,26 @@
225229 name = Frameworks;
226230 sourceTree = "<group>";
227231 };
232+ 5C0DDDC2106B563A008425EE /* Undo Manager */ = {
233+ isa = PBXGroup;
234+ children = (
235+ 5C0DDDC3106B5652008425EE /* ElisUndoManager.h */,
236+ 5C0DDDC4106B5652008425EE /* ElisUndoManager.m */,
237+ );
238+ name = "Undo Manager";
239+ sourceTree = "<group>";
240+ };
241+ 5C0DDF01106BB945008425EE /* Animation Layer */ = {
242+ isa = PBXGroup;
243+ children = (
244+ 5CE26AD5105BD8B50082C63A /* ElisAnimationLayerFactory.h */,
245+ 5CE26AD6105BD8B50082C63A /* ElisAnimationLayerFactory.m */,
246+ 5C808D68105CDA6800818B1A /* ElisCustomCALayer.h */,
247+ 5C808D69105CDA6800818B1A /* ElisCustomCALayer.m */,
248+ );
249+ name = "Animation Layer";
250+ sourceTree = "<group>";
251+ };
228252 5C56081C105FC9D20094F837 /* Core Image Kernel */ = {
229253 isa = PBXGroup;
230254 children = (
@@ -269,6 +293,8 @@
269293 children = (
270294 5CF28E0B1062581900C49262 /* ElisWriter.h */,
271295 5CF28E0C1062581900C49262 /* ElisWriter.m */,
296+ 5C8A480F106A66ED00EC2F3D /* ElisWriterLegacy.h */,
297+ 5C8A4810106A66ED00EC2F3D /* ElisWriterLegacy.m */,
272298 );
273299 name = Writer;
274300 sourceTree = "<group>";
@@ -351,6 +377,8 @@
351377 5C560821105FCA140094F837 /* ElisCustomFilter.m in Sources */,
352378 5CF28DC310624BCE00C49262 /* ElisMediaBrowserController.m in Sources */,
353379 5CF28E0D1062581900C49262 /* ElisWriter.m in Sources */,
380+ 5C8A4811106A66ED00EC2F3D /* ElisWriterLegacy.m in Sources */,
381+ 5C0DDDC5106B5652008425EE /* ElisUndoManager.m in Sources */,
354382 );
355383 runOnlyForDeploymentPostprocessing = 0;
356384 };
--- a/ElisBase.h
+++ b/ElisBase.h
@@ -40,7 +40,7 @@
4040
4141 // GCD使ったら表示がちらつくようになった。どういうことなの...
4242
43-//#define __SNOW_LEOPARD__
43+#define __SNOW_LEOPARD__
4444 //#define __SNOW_LEOPARD_GCD__
4545
4646 #ifdef __SNOW_LEOPARD_GCD__
--- a/ElisController.h
+++ b/ElisController.h
@@ -39,7 +39,8 @@
3939 #import "ElisAnimationLayerFactory.h"
4040 #import "ElisTimeLineController.h"
4141 #import "ElisCustomFilter.h"
42-#import "ElisWriter.h"
42+//#import "ElisWriter.h"
43+#import "ElisUndoManager.h"
4344
4445 @class ElisMainView, ElisTimeLineController, ElisPropertyTableController;
4546
@@ -55,7 +56,8 @@ int timeLineXShift;
5556 IBOutlet ElisTimeLineController* _timeLineController;
5657 IBOutlet ElisPropertyTableController* _tableController;
5758 IBOutlet NSWindow* _mainWindow;
58- IBOutlet ElisWriter* _writer;
59+ IBOutlet id _writer;
60+ IBOutlet ElisUndoManager* _undoManager;
5961
6062 float hipTime;
6163 QTTime _currentTime;
@@ -88,6 +90,8 @@ int timeLineXShift;
8890 - (IBAction)openProjectSaveDialog:(id)sender;
8991 - (IBAction)openProjectLoadDialog:(id)sender;
9092 - (IBAction)rewriteProject:(id)sender;
93+- (IBAction)undo:(id)sender;
94+- (IBAction)redo:(id)sender;
9195
9296 - (IBAction)changeToSmallWindiw:(id)sender;
9397
--- a/ElisController.m
+++ b/ElisController.m
@@ -173,7 +173,7 @@ static float convertQTTimeToSecond(QTTime t)
173173
174174 - (void)stop:(QTTime)time
175175 {
176- NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
176+// NSMutableArray* interestLayers = [[NSMutableArray alloc] init];
177177 int i, size = [layers count];
178178
179179 // hipTime = [self getHipTime];
@@ -188,7 +188,7 @@ static float convertQTTimeToSecond(QTTime t)
188188 // [(ElisLayer*)[interestLayers objectAtIndex:i] stop];
189189
190190 for(i = 0; i < size; i++)
191- [[layers objectAtIndex:i] stop];
191+ [(ElisLayer*)[layers objectAtIndex:i] stop];
192192
193193 playing = NO;
194194 globalCurrentTime = time;
@@ -318,8 +318,8 @@ static float convertQTTimeToSecond(QTTime t)
318318 if(code == NSCancelButton) return;
319319 [sheet close];
320320
321-// [_writer write:path];
322- [NSThread detachNewThreadSelector:@selector(write:) toTarget:_writer withObject:path];
321+// [_writer write:sheet];
322+ [NSThread detachNewThreadSelector:@selector(write:) toTarget:_writer withObject:sheet];
323323 }
324324
325325 // エフェクトのメニュー項目を構築
@@ -479,6 +479,12 @@ static float convertQTTimeToSecond(QTTime t)
479479 if([menuItem action] == @selector(deleteSelectLayer:))
480480 return [_timeLineController canDeleteLayer];
481481
482+ if([menuItem action] == @selector(undo:))
483+ return [_undoManager canUndo];
484+
485+ if([menuItem action] == @selector(redo:))
486+ return [_undoManager canRedo];
487+
482488 return YES;
483489 }
484490
@@ -499,4 +505,16 @@ static float convertQTTimeToSecond(QTTime t)
499505 [NSBundle loadNibNamed:@"MainMenuForSmallDisplay" owner:self];
500506 }
501507
508+- (IBAction)undo:(id)sender
509+{
510+ [_undoManager popOperation];
511+ [self refresh];
512+}
513+
514+- (IBAction)redo:(id)sender
515+{
516+ [_undoManager redoOperation];
517+ [self refresh];
518+}
519+
502520 @end
--- a/ElisLayer.h
+++ b/ElisLayer.h
@@ -1,5 +1,4 @@
11 //
2-// ElisLayer.h
32 // Copyright (c) 2009 Yanagi Asakura
43 //
54 // This software is provided 'as-is', without any express or implied
@@ -21,6 +20,7 @@
2120 // 3. This notice may not be removed or altered from any source
2221 // distribution.
2322
23+// ElisLayer.h
2424 // Elis Colors
2525 //
2626 // Created by 柳 on 09/09/12.
@@ -85,5 +85,8 @@
8585 - (float)duration;
8686 - (id)initWithCoder:(NSCoder*)coder;
8787 - (void)encodeWithCoder:(NSCoder*)encoder;
88+- (void)saveToEncoder:(NSCoder*)encoder;
89+- (void)loadFromDecoder:(NSCoder*)coder;
90+
8891
8992 @end
--- a/ElisLayer.m
+++ b/ElisLayer.m
@@ -29,6 +29,8 @@
2929
3030 #import "ElisLayer.h"
3131
32+#define TRACK_SIZE 32
33+
3234 static float convertQTTimeToSecond(QTTime t)
3335 {
3436 return (float)t.timeValue/t.timeScale;
@@ -88,8 +90,17 @@ static float convertQTTimeToSecond(QTTime t)
8890 QTTime begin = QTMakeTime(frame.origin.x*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
8991 QTTime d = QTMakeTime(frame.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
9092
91- trackNumber = floor(frame.origin.y/51.0);
93+// trackNumber = floor((frame.origin.y+1)/51.0);
94+ trackNumber = round((floor(frame.origin.y/51.0) * 51 + 1 + 25)/51.0);
9295 mapping = QTMakeTimeRange(begin, d);
96+
97+ int i, center = frame.origin.y + frame.size.height/2;
98+ for(i = 0; i < TRACK_SIZE; i++){ // これしきのことにループ回すってどういうことなの...
99+ if(51.0*i+1 <= center && center <= 51.0*(i+1)+1){
100+ trackNumber = i;
101+ return;
102+ }
103+ }
93104 }
94105
95106 - (void)changeOffset:(float)df
@@ -165,7 +176,9 @@ static float convertQTTimeToSecond(QTTime t)
165176 - (CIImage*)getEffectedImageWithoutStamp:(QTTime)time
166177 {
167178 QTTime innerTime = QTTimeDecrement(time, mapping.time);
168- CIImage* image = [media getFrameForQTTime:QTTimeIncrement(innerTime, offset)];
179+ [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
180+// CIImage* image = [media getFrameForQTTime:QTTimeIncrement(innerTime, offset)];
181+ CIImage* image = [media getFrameForTime:nil];
169182 if(image == nil) return nil;
170183
171184 return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];
@@ -291,11 +304,21 @@ static float convertQTTimeToSecond(QTTime t)
291304 - (void)getSoundTrack:(NSMutableArray*)soundTrack
292305 {
293306 QTTrack* t;
307+ QTTime qtr;
294308 t = [media getSoundTrack];
295309 if(t){
310+ [(QTMovie*)[media getSoundMovie] setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
311+ qtr = [media duration];
312+ mapping.time = QTMakeTime(convertQTTimeToSecond(mapping.time)*qtr.timeScale, qtr.timeScale);
313+ mapping.duration = QTMakeTime(convertQTTimeToSecond(mapping.duration)*qtr.timeScale, qtr.timeScale);
314+ [[media getSoundMovie] deleteSegment:QTMakeTimeRange(QTZeroTime, offset)];
315+ [[media getSoundMovie] insertEmptySegmentAt:QTMakeTimeRange(QTZeroTime, mapping.time)];
316+// [[media getSoundMovie] scaleSegment:qtr newDuration:QTMakeTimeRange(offset, mapping.duration)];
317+ [soundTrack addObject:[media getSoundMovie]];
296318 [soundTrack addObject:t];
297- [soundTrack addObject:[NSValue valueWithQTTime:offset]];
298- [soundTrack addObject:[NSValue valueWithQTTimeRange:mapping]];
319+ [soundTrack addObject:[NSValue valueWithQTTime:QTTimeIncrement(mapping.duration, mapping.time)]];
320+// [soundTrack addObject:[NSValue valueWithQTTime:offset]];
321+// [soundTrack addObject:[NSValue valueWithQTTimeRange:mapping]];
299322 }
300323 }
301324
@@ -308,8 +331,6 @@ static float convertQTTimeToSecond(QTTime t)
308331 [encoder encodeObject:effects forKey:@"effects"];
309332 [encoder encodeObject:pxKeyframe forKey:@"pxKerframe"];
310333 [encoder encodeObject:pyKeyframe forKey:@"pyKeyframe"];
311-
312- NSLog(@"encoding layer");
313334 }
314335
315336 - (id)initWithCoder:(NSCoder*)coder
@@ -322,15 +343,39 @@ static float convertQTTimeToSecond(QTTime t)
322343 pxKeyframe = [coder decodeObjectForKey:@"pxKeyframe"];
323344 pyKeyframe = [coder decodeObjectForKey:@"pyKeyframe"];
324345
325- NSLog(@"decoding layer");
326-
327346 return self;
328347 }
329348
349+- (void)saveToEncoder:(NSCoder*)encoder
350+{
351+ [encoder encodeInt:trackNumber forKey:@"trackNumber"];
352+ [encoder encodeObject:QTStringFromTimeRange(mapping) forKey:@"mapping"];
353+ [encoder encodeObject:QTStringFromTime(offset) forKey:@"offset"];
354+ [encoder encodeObject:effects forKey:@"effects"];
355+ [encoder encodeObject:pxKeyframe forKey:@"pxKerframe"];
356+ [encoder encodeObject:pyKeyframe forKey:@"pyKeyframe"];
357+
358+ NSLog(QTStringFromTimeRange(mapping));
359+}
360+
361+- (void)loadFromDecoder:(NSCoder*)coder
362+{
363+ trackNumber = [coder decodeIntForKey:@"trackNumber"];
364+ mapping = QTTimeRangeFromString([coder decodeObjectForKey:@"mapping"]);
365+ offset = QTTimeFromString([coder decodeObjectForKey:@"offset"]);
366+ effects = [coder decodeObjectForKey:@"effects"];
367+ pxKeyframe = [coder decodeObjectForKey:@"pxKeyframe"];
368+ pyKeyframe = [coder decodeObjectForKey:@"pyKeyframe"];
369+
370+ NSLog(QTStringFromTimeRange(mapping));
371+
372+ [self setLayer:alayer];
373+}
374+
330375 - (void)setLayer:(CALayer*)layer
331376 {
332377 layer.frame = CGRectMake(convertQTTimeToSecond(mapping.time)*timeLineScale, trackNumber*51+1,
333- (convertQTTimeToSecond(mapping.time) + convertQTTimeToSecond(mapping.duration))*timeLineScale, 50);
378+ (/*convertQTTimeToSecond(mapping.time) + */convertQTTimeToSecond(mapping.duration))*timeLineScale, 50);
334379 [self setAlayer:layer];
335380 }
336381
--- a/ElisMainView.m
+++ b/ElisMainView.m
@@ -248,10 +248,18 @@ static CVReturn MyRenderCallback(CVDisplayLinkRef displayLink,
248248 timeOffset = time;
249249 }
250250
251-- (void)getCurrentPixelData:(NSRect)rect buffer:(unsigned char*)buffer
251+- (void)getCurrentPixelData:(NSRect)rect buffer:(void*)buffer
252252 {
253- glReadBuffer(GL_FRONT); // フロントバッファ(って何だろう?)からピクセルを読みに行く。
254- glReadPixels(0, 0, rect.size.width, rect.size.height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
253+ glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
254+ glPixelStorei(GL_PACK_ALIGNMENT, 4);
255+ glPixelStorei(GL_PACK_ROW_LENGTH, 0);
256+ glPixelStorei(GL_PACK_SKIP_ROWS, 0);
257+ glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
258+
259+// glReadBuffer(GL_FRONT); // フロントバッファ(って何だろう?)からピクセルを読みに行く。
260+ glReadPixels(0, 0, rect.size.width, rect.size.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
261+
262+ glPopClientAttrib();
255263 }
256264
257265 @end
--- a/ElisMedia.m
+++ b/ElisMedia.m
@@ -32,7 +32,7 @@
3232
3333 @implementation ElisMedia
3434
35-// QuickTime X を試すためにかなり書き換えた。けど戻した、
35+// QuickTime X を試すためにかなり書き換えた。けど戻した。
3636 - (id)initWithMovieFile:(NSString*)path
3737 {
3838 image = nil;
@@ -156,8 +156,10 @@
156156 - (void)setCurrentTime:(QTTime)time
157157 {
158158 // time.timeValue *= speed;
159- if(movie)
159+ if(movie){
160160 [movie setAttribute:[NSValue valueWithQTTime:time] forKey:QTMovieCurrentTimeAttribute];
161+ MoviesTask([movie quickTimeMovie], 0);
162+ }
161163 if(sound)
162164 [sound setCurrentTime:time];
163165 }
@@ -275,4 +277,12 @@
275277
276278 }
277279
280+- (QTMovie*)getSoundMovie
281+{
282+ if(sound)
283+ return sound;
284+ else
285+ return nil;
286+}
287+
278288 @end
--- a/ElisMediaBrowserController.m
+++ b/ElisMediaBrowserController.m
@@ -127,7 +127,7 @@ static NSArray *openFiles()
127127 [_mediaBrowser setAllowsReordering:YES];
128128 [_mediaBrowser setAnimates:YES];
129129 [_mediaBrowser setDraggingDestinationDelegate:self];
130- // [_imageBrowser setBackgroundColor:[NSColor clearColor]];
130+// [_mediaBrowser setBackgroundColor:[NSColor grayColor]];
131131 }
132132
133133 /* entry point for reloading image-browser's data and setNeedsDisplay */
--- a/ElisTimeLineController.h
+++ b/ElisTimeLineController.h
@@ -50,6 +50,7 @@ float timeLineScale;
5050 IBOutlet id _timeLineView;
5151 IBOutlet id _mainController;
5252 IBOutlet id _tableController;
53+ IBOutlet id _undoManager;
5354 CALayer* draggingLayer;
5455
5556 NSPoint clickedPosition;
--- a/ElisTimeLineController.m
+++ b/ElisTimeLineController.m
@@ -103,6 +103,7 @@
103103 draggingLayer = newLayer;
104104 [timeLine addSublayer:newLayer];
105105 clickedPosition.x = -1;
106+// [_undoManager pushOperation:[draggingLayer valueForKey:@"ElisLayer"]];
106107 }
107108
108109 - (void)readyInDrag:(NSPoint)p
@@ -143,6 +144,7 @@
143144 clickedPosition = point;
144145 clickedLayerPosition = *(CGPoint*)&point;
145146 [self changeLayerPosition:draggingLayer position:point];
147+// [_undoManager pushOperation:[draggingLayer valueForKey:@"ElisLayer"]];
146148 NSLog(@"%f", draggingLayer.frame.origin.x);
147149 } /*else*/ {
148150 float dx = clickedPosition.x - point.x;
@@ -160,11 +162,13 @@
160162 point.y = floor(point.y/51.0) * 51 + 1 + 25; // +25ってどこから出てきた?
161163 draggingLayer.position = point;
162164 draggingLayer.opacity = 0.75;
165+ [_undoManager pushOperation:[draggingLayer valueForKey:@"ElisLayer"]];
163166 draggingLayer = nil;
164167 clickedPosition.x = -1;
165168 dragging = NO;
166169 // [_timeLineView setCursorRect:NSZeroRect]; // これなに?
167170 }
171+ if(stretch != 0) [_undoManager pushOperation:[draggingLayer valueForKey:@"ElisLayer"]];
168172 [_timeLineView setCursorRect:draggingLayer.frame];
169173 stretch = 0;
170174 }
@@ -227,6 +231,7 @@
227231 [_tableController createPropertyTable:[draggingLayer valueForKey:@"ElisLayer"]];
228232 [_tableController reload];
229233 [_mainController refresh];
234+ [_undoManager pushOperation:[draggingLayer valueForKey:@"ElisLayer"]];
230235 return;
231236 }
232237 }
--- a/ElisTimeLineView.h
+++ b/ElisTimeLineView.h
@@ -36,6 +36,7 @@
3636 @interface ElisTimeLineView : NSView {
3737 IBOutlet id _timeLineController;
3838 IBOutlet id _mainController;
39+ IBOutlet id _undoManager;
3940 NSRect leftCursorRect, rightCursorRect;
4041 }
4142
--- /dev/null
+++ b/ElisUndoManager.h
@@ -0,0 +1,28 @@
1+//
2+// ElisUndoManager.h
3+// Elis Colors
4+//
5+// Created by 柳 on 09/09/24.
6+// Copyright 2009 __MyCompanyName__. All rights reserved.
7+//
8+
9+// 「リアルタイムで全ての値が変化する」アプリケーションでも使えるUndoManager。オレオレ実装。
10+// レイヤーを一単位としてバックアップ取ってるだけ。メモリ効率すっごい悪いよ!
11+
12+// まだ実装途中。
13+
14+#import <Cocoa/Cocoa.h>
15+#import "ElisBase.h"
16+#import "ElisLayer.h"
17+
18+@interface ElisUndoManager : NSObject {
19+ NSMutableArray* undoStack;
20+ int index;
21+
22+ IBOutlet id _mainController;
23+}
24+
25+- (BOOL)canUndo;
26+- (void)popOperation;
27+
28+@end
--- /dev/null
+++ b/ElisUndoManager.m
@@ -0,0 +1,70 @@
1+//
2+// ElisUndoManager.m
3+// Elis Colors
4+//
5+// Created by 柳 on 09/09/24.
6+// Copyright 2009 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import "ElisUndoManager.h"
10+
11+
12+@implementation ElisUndoManager
13+
14+- (void)awakeFromNib
15+{
16+ undoStack = [[NSMutableArray alloc] init];
17+ index = 0;
18+}
19+
20+- (void)pushOperation:(ElisLayer*)layer
21+{
22+ NSMutableData* data = [[NSMutableData alloc] init];
23+ NSKeyedArchiver* encoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
24+
25+ [layer saveToEncoder:encoder];
26+ [encoder finishEncoding];
27+
28+// [undoStack addObject:layer];
29+// [undoStack addObject:data];
30+ [undoStack removeObjectsInRange:NSMakeRange(index, [undoStack count] - index)];
31+
32+ if(index != 0)
33+ if([data isEqualToData:[undoStack objectAtIndex:index-1]])
34+ return;
35+
36+ [undoStack insertObject:layer atIndex:index];
37+ [undoStack insertObject:data atIndex:index+1];
38+ index += 2;
39+}
40+
41+- (void)popOperation
42+{
43+ NSData* data = [undoStack objectAtIndex:index-1];
44+ ElisLayer* layer = [undoStack objectAtIndex:index-2];
45+
46+ NSKeyedUnarchiver* decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
47+ [layer loadFromDecoder:decoder];
48+ [decoder finishDecoding];
49+
50+ index -= 2;
51+}
52+
53+- (void)redoOperation
54+{
55+ index += 4;
56+ [self popOperation];
57+}
58+
59+- (BOOL)canUndo
60+{
61+ return index != 0;
62+ return [undoStack count] != 0;
63+}
64+
65+- (BOOL)canRedo
66+{
67+ return index+2 < [undoStack count];
68+}
69+
70+@end
--- a/ElisWriter.h
+++ b/ElisWriter.h
@@ -27,7 +27,8 @@
2727 // Copyright 2009 __MyCompanyName__. All rights reserved.
2828 //
2929
30-// ファイルへの書き出しを担当するクラス。
30+// ファイルへの書き出しを担当するクラス。QTKitベース。
31+// 今は使っていない。
3132
3233 #import <Cocoa/Cocoa.h>
3334 #import "ElisBase.h"
--- a/ElisWriter.m
+++ b/ElisWriter.m
@@ -97,10 +97,15 @@
9797
9898 image = [[NSImage alloc] init];
9999 [image addRepresentation:rep];
100- [outputMovie addImage:image forDuration:QTMakeTime(1, fps) withAttributes:attrs];
101-// [_bar setDoubleValue:frame/totalFrames];
100+ [self performSelectorOnMainThread:@selector(addImage:) withObject:image waitUntilDone:YES];
101+// [outputMovie addImage:image forDuration:QTMakeTime(1, fps) withAttributes:attrs];
102102 [self performSelectorOnMainThread:@selector(changeBarValue:)
103103 withObject:[NSNumber numberWithDouble:(double)frame/totalFrames] waitUntilDone:YES];
104+
105+ if([outputMovie canUpdateMovieFile])
106+ [outputMovie updateMovieFile];
107+
108+ NSLog(@"%d / %d", frame, totalFrames);
104109 }
105110
106111 free(buffer);
@@ -115,6 +120,11 @@
115120 [NSApp endSheet:_barSheet];
116121 }
117122
123+- (void)addImage:(id)image
124+{
125+ [outputMovie addImage:image forDuration:QTMakeTime(1, fps) withAttributes:attrs];
126+}
127+
118128 - (void)initializeMovie:(NSString*)path
119129 {
120130 outputMovie = [[QTMovie alloc] initToWritableFile:path error:nil];
--- /dev/null
+++ b/ElisWriterLegacy.h
@@ -0,0 +1,46 @@
1+//
2+// ElisWriterLegacy.h
3+// Elis Colors
4+//
5+// Created by 柳 on 09/09/23.
6+// Copyright 2009 __MyCompanyName__. All rights reserved.
7+//
8+
9+// レガシーな動画書き出し器。
10+// この古代な感じはどうにかならないの?
11+
12+#import <Cocoa/Cocoa.h>
13+#import "ElisBase.h"
14+#import "ElisController.h"
15+
16+#define GAMMA 0.81818181
17+
18+@interface ElisWriterLegacy : NSObject {
19+
20+ IBOutlet id _mainView;
21+ IBOutlet id _mainController;
22+ IBOutlet id _barSheet;
23+ IBOutlet id _bar;
24+ IBOutlet id _mainWindow;
25+
26+ NSRect outputSize;
27+ unsigned char* gamma_table;
28+
29+
30+ QTTime movieDuration;
31+
32+ BOOL isExporting;
33+ BOOL cancelExport;
34+ char *contextPixels; // readback buffer for the compression
35+ char *flippedContextPixels; // another buffer to flip the pixels as we read from the screen
36+ UInt32 contextRowBytes;
37+ int outputWidth;
38+ int outputHeight;
39+ int outputAlignment;
40+ ImageDescriptionHandle outputImageDescription; // describes our compression
41+
42+ MovieExportComponent _myExporter;
43+ BOOL _myCancelled;
44+}
45+
46+@end
--- /dev/null
+++ b/ElisWriterLegacy.m
@@ -0,0 +1,438 @@
1+//
2+// ElisWriterLegacy.m
3+// Elis Colors
4+//
5+// Created by 柳 on 09/09/23.
6+// Copyright 2009 __MyCompanyName__. All rights reserved.
7+//
8+
9+#import "ElisWriterLegacy.h"
10+
11+// Handle requests for information about the output video data
12+static OSErr QTMoovProcs_VideoTrackPropertyProc (void *theRefcon, long theTrackID, OSType thePropertyType, void *thePropertyValue)
13+{
14+#pragma unused(theRefcon, theTrackID)
15+
16+ OSErr myErr = noErr;
17+
18+ switch (thePropertyType) {
19+ case movieExportUseConfiguredSettings:
20+ *(Boolean *)thePropertyValue = true;
21+ break;
22+
23+ default:
24+ myErr = paramErr; // non-zero value means: use default value provided by export component
25+ break;
26+ }
27+
28+ return(myErr);
29+}
30+
31+
32+//--------------------------------------------------------------------------------------------------
33+
34+// Provide the output audio data.
35+// ハンドラ的なもの?
36+static OSErr QTMoovProcs_VideoTrackDataProc(void *theRefcon, MovieExportGetDataParams *theParams)
37+{
38+ return [(ElisWriterLegacy*)theRefcon exportFrame:theParams];
39+}
40+
41+
42+@implementation ElisWriterLegacy
43+
44+- (void)awakeFromNib
45+{
46+ gamma_table = malloc(sizeof(unsigned char) * 256);
47+}
48+
49+- (void)write:(NSSavePanel*)sp
50+{
51+ [self reallyExportMovie:sp toPod:NO];
52+}
53+
54+-(void)reallyExportMovie:(NSSavePanel *)savePanel toPod:(BOOL)exportToPod
55+{
56+ MovieExportComponent myExporter = NULL;
57+ ComponentDescription myCompDesc;
58+ Boolean myCancelled = false;
59+ long trackID;
60+ MovieExportGetPropertyUPP theAudioPropProcUPP = nil;
61+ MovieExportGetDataUPP theAudioDataProcUPP = nil;
62+ TimeScale audioScale = 0;
63+ void *audioRefCon = 0;
64+
65+ OSErr err = noErr;
66+
67+ // 下準備
68+ float floatTime;
69+ floatTime = [_mainController getHipTime];
70+ movieDuration = QTMakeTime(floatTime*DEFAULT_FPS, DEFAULT_FPS);
71+ [self readyGammmaTable];
72+
73+ // プログレスバーを表示
74+ [NSApp beginSheet:_barSheet modalForWindow:_mainWindow
75+ modalDelegate:self didEndSelector:nil contextInfo:NULL];
76+
77+ // Export into a Quicktime movie
78+ myCompDesc.componentType = MovieExportType;
79+ myCompDesc.componentSubType = MovieFileType;
80+ myCompDesc.componentManufacturer = kAppleManufacturer;
81+ myCompDesc.componentFlags = canMovieExportFromProcedures;
82+ myCompDesc.componentFlagsMask = canMovieExportFromProcedures;
83+
84+ // open the selected movie export component
85+ myExporter = OpenComponent(FindNextComponent(NULL, &myCompDesc));
86+ if (myExporter == NULL) {
87+ NSLog(@"could not find export compontent !");
88+ return;
89+ }
90+
91+ // Hey exporter, support modern audio features
92+ Boolean useHighResolutionAudio = true;
93+ QTSetComponentProperty(myExporter, kQTPropertyClass_MovieExporter,
94+ kQTMovieExporterPropertyID_EnableHighResolutionAudioFeatures,
95+ sizeof(Boolean),
96+ &useHighResolutionAudio);
97+
98+ // create UPPs for the two app-defined export functions
99+ MovieExportGetPropertyUPP theVideoPropProcUPP = NewMovieExportGetPropertyUPP(QTMoovProcs_VideoTrackPropertyProc);
100+ MovieExportGetDataUPP theVideoDataProcUPP = NewMovieExportGetDataUPP(QTMoovProcs_VideoTrackDataProc);
101+
102+ // インスタンス変数を使ってる!
103+ MovieExportAddDataSource(myExporter, VideoMediaType,
104+ movieDuration.timeScale, // use the original timescale
105+ &trackID,
106+ theVideoPropProcUPP,
107+ theVideoDataProcUPP,
108+ self);
109+
110+ // とりあえずいらない
111+ // setup audio
112+ NSMutableArray* audioTracks = [[NSMutableArray alloc] init];
113+ [_mainController getSoundTrack:audioTracks];
114+ int aui, tsize = [audioTracks count];
115+ QTTime qtr;
116+ for(aui = 0; aui < tsize; aui += 3){
117+ // we are setting up the audio for pass through
118+ // インスタンス変数を使ってる!
119+ qtr = [[audioTracks objectAtIndex:aui+2] QTTimeValue];
120+ err = MovieExportNewGetDataAndPropertiesProcs(myExporter, SoundMediaType,
121+ &audioScale,
122+ [[audioTracks objectAtIndex:aui] quickTimeMovie],
123+ [[audioTracks objectAtIndex:aui+1] quickTimeTrack], // we only use the first audio here
124+ 0,
125+ qtr.timeValue,
126+ &theAudioPropProcUPP,
127+ &theAudioDataProcUPP,
128+ &audioRefCon);
129+ if (err) {
130+ NSLog(@"Can't get audio for export");
131+ } else {
132+ MovieExportAddDataSource(myExporter, SoundMediaType, audioScale, &trackID, theAudioPropProcUPP, theAudioDataProcUPP, audioRefCon);
133+ }
134+ }
135+
136+ // これは使う。
137+ if (NO == exportToPod) {
138+ // インスタンス変数を使ってる!
139+ _myExporter = myExporter;
140+ [self performSelectorOnMainThread:@selector(movieExportDialogMainThread) withObject:nil waitUntilDone:YES];
141+// MovieExportDoUserDialog(myExporter, NULL, NULL, 0, movieDuration.timeValue, &myCancelled);
142+ myExporter = _myExporter;
143+ myCancelled = _myCancelled;
144+
145+ if (myCancelled) {
146+ NSLog(@"User canceled export dialog");
147+ DisposeMovieExportGetPropertyUPP(theVideoPropProcUPP);
148+ DisposeMovieExportGetDataUPP(theVideoDataProcUPP);
149+
150+ if (theAudioPropProcUPP && theAudioDataProcUPP) {
151+ MovieExportDisposeGetDataAndPropertiesProcs(myExporter, theAudioPropProcUPP, theAudioDataProcUPP, audioRefCon);
152+ }
153+
154+ CloseComponent(myExporter);
155+
156+ return;
157+ }
158+ } else {
159+ // いらない
160+ // Setup the Movie Export component with our preset export settings
161+// QTAtomContainer settings;
162+//
163+// PtrToHand(ExportSettings, (Handle *)&settings, sizeof(ExportSettings));
164+//
165+// MovieExportSetSettingsFromAtomContainer(myExporter, settings);
166+//
167+// QTDisposeAtomContainer(settings);
168+ }
169+
170+ isExporting = YES;
171+ cancelExport = NO;
172+
173+ OSType myDataType;
174+ Handle myDataRef;
175+
176+ NSRect frame = *(NSRect*)&ProjectMovieSize;
177+ outputSize = frame;
178+
179+ // create the readback and flipping buffers - see note about flipping in exportFrame method
180+ // インスタンス変数やまもり
181+ outputWidth = frame.size.width;
182+ outputHeight = frame.size.height;
183+ //outputWidth = 720;
184+ //outputHeight = 480;
185+ outputAlignment = 4;
186+ contextRowBytes = outputWidth * outputAlignment;
187+ contextPixels = calloc(contextRowBytes * outputHeight, sizeof(char));
188+ flippedContextPixels = calloc(contextRowBytes * outputHeight, sizeof(char));
189+
190+ // setup the image description for the frame compression
191+ outputImageDescription = (ImageDescriptionHandle)NewHandleClear(sizeof(ImageDescription));
192+ (*outputImageDescription)->idSize = sizeof(ImageDescription);
193+#ifdef __BIG_ENDIAN__
194+ (*outputImageDescription)->cType = k32ARGBPixelFormat;
195+#else
196+ (*outputImageDescription)->cType = k32BGRAPixelFormat;
197+#endif
198+ (*outputImageDescription)->vendor = kAppleManufacturer;
199+ (*outputImageDescription)->spatialQuality = codecLosslessQuality;
200+ (*outputImageDescription)->width = outputWidth;
201+ (*outputImageDescription)->height = outputHeight;
202+ (*outputImageDescription)->hRes = 72L<<16;
203+ (*outputImageDescription)->vRes = 72L<<16;
204+ (*outputImageDescription)->dataSize = contextRowBytes * outputHeight;
205+ (*outputImageDescription)->frameCount = 1;
206+ (*outputImageDescription)->depth = 32;
207+ (*outputImageDescription)->clutID = -1;
208+
209+ [NSApp beginSheet:_barSheet modalForWindow:_mainWindow
210+ modalDelegate:self didEndSelector:nil contextInfo:NULL];
211+
212+ [[NSFileManager defaultManager] removeFileAtPath:[savePanel filename] handler:nil];
213+ // export the video data to the data reference
214+ QTNewDataReferenceFromCFURL((CFURLRef)[savePanel URL], 0, &myDataRef, &myDataType );
215+
216+ // メインの処理はここじゃね。
217+ MovieExportFromProceduresToDataRef(myExporter, myDataRef, myDataType);
218+
219+ // we are done with the .mov export so lets clean up
220+ // 終了処理?
221+ free(contextPixels);
222+ contextPixels = nil;
223+ free(flippedContextPixels);
224+ flippedContextPixels = nil;
225+ DisposeMovieExportGetPropertyUPP(theVideoPropProcUPP);
226+ DisposeMovieExportGetDataUPP(theVideoDataProcUPP);
227+
228+ if (theAudioPropProcUPP && theAudioDataProcUPP) {
229+ MovieExportDisposeGetDataAndPropertiesProcs(myExporter, theAudioPropProcUPP, theAudioDataProcUPP, audioRefCon);
230+ }
231+
232+ if (outputImageDescription) DisposeHandle((Handle)outputImageDescription);
233+ outputImageDescription = NULL;
234+
235+ CloseComponent(myExporter);
236+
237+ // do some extra work if we're exporting to iPod
238+ // いらない。
239+// if (!cancelExport && YES == exportToPod) {
240+// Handle podExportDataRef;
241+// OSType podExportDataRefType;
242+// Movie theRecentlyExportedMovie;
243+// short resID = movieInDataForkResID;
244+//
245+// // open the movie we just exported
246+// NewMovieFromDataRef(&theRecentlyExportedMovie, newMovieActive, &resID, myDataRef, myDataType);
247+//
248+// // create a new data reference using the .m4v extention
249+// CFMutableStringRef newFileName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, (CFStringRef)[savePanel filename]);
250+// CFRange extension = CFStringFind(newFileName, CFSTR(".mov"), kCFCompareBackwards);
251+// CFStringReplace(newFileName, extension, CFSTR(".m4v"));
252+//
253+// QTNewDataReferenceFromFullPathCFString(newFileName, kQTNativeDefaultPathStyle, 0, &podExportDataRef, &podExportDataRefType);
254+//
255+// // Delete any existing .m4v file with the same name
256+// [[NSFileManager defaultManager] removeFileAtPath:(NSString *)newFileName handler:nil];
257+//
258+// // find and open the iPod export component, if you wanted to export to ATV use the 'M4VH' fourCC
259+// err = OpenADefaultComponent(MovieExportType, 'M4V ', &myExporter);
260+// if (err == noErr && 0 != myExporter) {
261+//
262+// // set the progress procedure for some basic UI
263+// MovieExportSetProgressProc(myExporter, NewMovieProgressUPP(QTMoovProcs_PodExportProgress), (long)delegate);
264+//
265+// // do the export
266+// MovieExportToDataRef(myExporter, podExportDataRef, podExportDataRefType, theRecentlyExportedMovie, 0, 0, GetMovieDuration(theRecentlyExportedMovie));
267+//
268+// // clean up
269+// CloseComponent(myExporter);
270+// DisposeHandle(podExportDataRef);
271+// DisposeMovie(theRecentlyExportedMovie);
272+//
273+// // delete the original .mov file which we don't need anymore
274+// [[NSFileManager defaultManager] removeFileAtPath:[savePanel filename] handler:nil];
275+//
276+// // open the .m4v in QuickTime Player -- just using openFile would result in iTunes starting up (not what I want to happen)
277+// [[NSWorkspace sharedWorkspace] openFile:(NSString *)newFileName withApplication:@"QuickTime Player"];
278+// }
279+//
280+// } else if (!cancelExport) {
281+//
282+// // open the movie in the QuickTime Player
283+// // これもいらないね。
284+// [[NSWorkspace sharedWorkspace] openFile:[savePanel filename]];
285+// }
286+
287+ // dispose the original data reference
288+ DisposeHandle(myDataRef);
289+
290+ // got back to the beginning of the movie
291+// QTTime currentTime = { 0, movieDuration.timeScale, 0 };
292+//
293+// [qtMovie setCurrentTime: currentTime];
294+// MoviesTask([qtMovie quickTimeMovie], 0); // QTKit is not doing this automatically
295+//
296+// // render the frame
297+// [self updateCurrentFrame];
298+// [self display];
299+
300+ [_barSheet close];
301+ [NSApp endSheet:_barSheet];
302+
303+ isExporting = NO;
304+}
305+
306+// この関数が出力フレームごとに呼ばれるはず。
307+- (OSErr)exportFrame:(MovieExportGetDataParams *)theParams
308+{
309+ if (cancelExport) return(userCanceledErr);
310+
311+ if (theParams->requestedTime > movieDuration.timeValue) return(eofErr);
312+
313+ NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init]; // As the export is done in a tight loop it is a good idea to have an
314+ // autorelease pool in the render frame call so we don't acumulate
315+ // objects over the lengthy progress and therefore fill the memory
316+ QTTime currentTime;
317+
318+ currentTime.timeValue = theParams->requestedTime;
319+ currentTime.timeScale = movieDuration.timeScale;
320+ currentTime.flags = 0;
321+
322+// [qtMovie setCurrentTime:currentTime];
323+// MoviesTask([qtMovie quickTimeMovie], 0); // QTKit is not doing this automatically
324+
325+ // render the frame
326+// [self updateCurrentFrame];
327+// [self display];
328+// [self performSelectorOnMainThread:@selector(renderFrame2:) withObject:[NSValue valueWithQTTime:currentTime] waitUntilDone:YES];
329+ [_mainView getFrameForQTTime:currentTime];
330+
331+ // read the frame from the context into our buffer
332+// if([self readbackFrameIntoBuffer:contextPixels alignment:outputAlignment width:outputWidth height:outputHeight offsetX:0 offsetY:0]) {
333+// NSLog(@"could not readback image!");
334+// }
335+ [_mainView getCurrentPixelData:outputSize buffer:contextPixels];
336+
337+ /* WHY IS THIS memcpy ROUTINE HERE?
338+ The way the pixels are read back through glReadPixels is flipped to what QuickTime expects.
339+ This can easily be worked around by rendering upside down - just switch the minY and maxY in glOrtho.
340+ But since we display the exported image during the export process in this example, we don't want to do this
341+ for visual purposes (because the image on the screen would end up being upside down),
342+ therefore we resort to flipping the image by hand.
343+ */
344+ int i = outputHeight;
345+ while(--i > 0) {
346+ memcpy(flippedContextPixels + ((outputHeight - i - 1) * contextRowBytes), contextPixels + (i * contextRowBytes), contextRowBytes);
347+ }
348+
349+ // end flipping code
350+
351+ // カラーシフトする分をガンマ補正。これはひどい。
352+ [self gammaAdjust:flippedContextPixels size:outputHeight*outputWidth*4];
353+
354+ // fill the return parameters for the compression
355+ theParams->actualTime = theParams->requestedTime;
356+ theParams->dataPtr = (void*)flippedContextPixels;
357+ theParams->dataSize = (**(outputImageDescription)).dataSize;
358+ theParams->desc = (SampleDescriptionHandle)outputImageDescription;
359+ theParams->descType = VideoMediaType;
360+ theParams->descSeed = 1;
361+ theParams->actualSampleCount = 1;
362+ theParams->durationPerSample = currentTime.timeScale / 30;
363+ theParams->sampleFlags = 0L;
364+
365+ [myPool release];
366+
367+// NSLog(@"%f [s]", (float)currentTime.timeValue/currentTime.timeScale);
368+ [self performSelectorOnMainThread:@selector(changeBarValue:)
369+ withObject:[NSNumber numberWithDouble:(double)currentTime.timeValue/movieDuration.timeValue]
370+ waitUntilDone:YES];
371+
372+ return noErr;
373+}
374+
375+- (void)changeBarValue:(NSNumber*)v
376+{
377+ [_bar setDoubleValue:[v doubleValue]];
378+}
379+
380+- (void)renderFrame2:(NSValue*)v
381+{
382+ [_mainView getFrameForQTTime:[v QTTimeValue]];
383+}
384+
385+- (void)finalize
386+{
387+ free(gamma_table);
388+ [super finalize];
389+}
390+
391+- (void)readyGammmaTable
392+{
393+ int i;
394+
395+ for(i = 0; i < 256; i++)
396+ gamma_table[i] = (unsigned char)255.0 * pow(i/255.0, 1.0/GAMMA);
397+}
398+
399+- (void)gammaAdjust:(unsigned char*)pixels size:(int)s
400+{
401+ int i;
402+ for(i = 0; i < s; i++){
403+ if(i%4 == 3) continue;
404+ pixels[i] = gamma_table[pixels[i]];
405+ }
406+}
407+
408+- (void)movieExportDialogMainThread
409+{
410+ MovieExportDoUserDialog(_myExporter, NULL, NULL, 0, movieDuration.timeValue, &_myCancelled);
411+}
412+
413+- (NSMutableArray*)getAudioTrack
414+{
415+ NSMutableArray* soundTrack = [[NSMutableArray alloc] init];
416+ QTTrack* track, *newTrack;
417+ int i, size;
418+ QTTime offset;
419+ QTTimeRange mapping;
420+ NSMutableArray* result = [[NSMutableArray alloc] init];
421+
422+ [_mainController getSoundTrack:soundTrack];
423+ size = [soundTrack count];
424+
425+ for(i = 0; i < size; i += 4){
426+ newTrack = [[QTTrack alloc] init];
427+ track = [soundTrack objectAtIndex:i+1];
428+ offset = [[soundTrack objectAtIndex:i+2] QTTimeValue];
429+ mapping = [[soundTrack objectAtIndex:i+3] QTTimeRangeValue];
430+ [newTrack insertSegmentOfTrack:track timeRange:QTMakeTimeRange(offset, mapping.duration) atTime:mapping.time];
431+ [result addObject:[soundTrack objectAtIndex:i]];
432+ [result addObject:newTrack];
433+ }
434+
435+ return result;
436+}
437+
438+@end
--- a/English.lproj/MainMenu.xib
+++ b/English.lproj/MainMenu.xib
@@ -21,8 +21,9 @@
2121 </object>
2222 <object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
2323 <bool key="EncodedWithXMLCoder">YES</bool>
24- <integer value="57"/>
24+ <integer value="205"/>
2525 <integer value="372"/>
26+ <integer value="625"/>
2627 </object>
2728 <object class="NSArray" key="IBDocument.PluginDependencies">
2829 <bool key="EncodedWithXMLCoder">YES</bool>
@@ -2118,7 +2119,7 @@
21182119 <nil key="NSViewClass"/>
21192120 <string key="NSWindowContentMaxSize">{1.79769e+308, 1.79769e+308}</string>
21202121 <object class="NSView" key="NSWindowView" id="326277469">
2121- <nil key="NSNextResponder"/>
2122+ <reference key="NSNextResponder"/>
21222123 <int key="NSvFlags">256</int>
21232124 <object class="NSMutableArray" key="NSSubviews">
21242125 <bool key="EncodedWithXMLCoder">YES</bool>
@@ -2149,10 +2150,17 @@
21492150 </object>
21502151 </object>
21512152 <string key="NSFrameSize">{480, 86}</string>
2153+ <reference key="NSSuperview"/>
21522154 </object>
21532155 <string key="NSScreenRect">{{0, 0}, {1920, 1178}}</string>
21542156 <string key="NSMaxSize">{1.79769e+308, 1.79769e+308}</string>
21552157 </object>
2158+ <object class="NSCustomObject" id="920214336">
2159+ <string key="NSClassName">ElisWriterLegacy</string>
2160+ </object>
2161+ <object class="NSCustomObject" id="943689817">
2162+ <string key="NSClassName">ElisUndoManager</string>
2163+ </object>
21562164 </object>
21572165 <object class="IBObjectContainer" key="IBDocument.Objects">
21582166 <object class="NSMutableArray" key="connectionRecords">
@@ -2223,14 +2231,6 @@
22232231 </object>
22242232 <object class="IBConnectionRecord">
22252233 <object class="IBActionConnection" key="connection">
2226- <string key="label">undo:</string>
2227- <reference key="source" ref="1014"/>
2228- <reference key="destination" ref="1058277027"/>
2229- </object>
2230- <int key="connectionID">223</int>
2231- </object>
2232- <object class="IBConnectionRecord">
2233- <object class="IBActionConnection" key="connection">
22342234 <string key="label">copy:</string>
22352235 <reference key="source" ref="1014"/>
22362236 <reference key="destination" ref="860595796"/>
@@ -2279,14 +2279,6 @@
22792279 </object>
22802280 <object class="IBConnectionRecord">
22812281 <object class="IBActionConnection" key="connection">
2282- <string key="label">redo:</string>
2283- <reference key="source" ref="1014"/>
2284- <reference key="destination" ref="790794224"/>
2285- </object>
2286- <int key="connectionID">231</int>
2287- </object>
2288- <object class="IBConnectionRecord">
2289- <object class="IBActionConnection" key="connection">
22902282 <string key="label">selectAll:</string>
22912283 <reference key="source" ref="1014"/>
22922284 <reference key="destination" ref="583158037"/>
@@ -3071,14 +3063,6 @@
30713063 </object>
30723064 <object class="IBConnectionRecord">
30733065 <object class="IBOutletConnection" key="connection">
3074- <string key="label">_writer</string>
3075- <reference key="source" ref="690852348"/>
3076- <reference key="destination" ref="717862185"/>
3077- </object>
3078- <int key="connectionID">631</int>
3079- </object>
3080- <object class="IBConnectionRecord">
3081- <object class="IBOutletConnection" key="connection">
30823066 <string key="label">_mainController</string>
30833067 <reference key="source" ref="717862185"/>
30843068 <reference key="destination" ref="690852348"/>
@@ -3125,6 +3109,94 @@
31253109 </object>
31263110 <int key="connectionID">646</int>
31273111 </object>
3112+ <object class="IBConnectionRecord">
3113+ <object class="IBOutletConnection" key="connection">
3114+ <string key="label">_mainController</string>
3115+ <reference key="source" ref="920214336"/>
3116+ <reference key="destination" ref="690852348"/>
3117+ </object>
3118+ <int key="connectionID">648</int>
3119+ </object>
3120+ <object class="IBConnectionRecord">
3121+ <object class="IBOutletConnection" key="connection">
3122+ <string key="label">_mainView</string>
3123+ <reference key="source" ref="920214336"/>
3124+ <reference key="destination" ref="132559063"/>
3125+ </object>
3126+ <int key="connectionID">649</int>
3127+ </object>
3128+ <object class="IBConnectionRecord">
3129+ <object class="IBOutletConnection" key="connection">
3130+ <string key="label">_writer</string>
3131+ <reference key="source" ref="690852348"/>
3132+ <reference key="destination" ref="920214336"/>
3133+ </object>
3134+ <int key="connectionID">650</int>
3135+ </object>
3136+ <object class="IBConnectionRecord">
3137+ <object class="IBOutletConnection" key="connection">
3138+ <string key="label">_barSheet</string>
3139+ <reference key="source" ref="920214336"/>
3140+ <reference key="destination" ref="34222678"/>
3141+ </object>
3142+ <int key="connectionID">651</int>
3143+ </object>
3144+ <object class="IBConnectionRecord">
3145+ <object class="IBOutletConnection" key="connection">
3146+ <string key="label">_bar</string>
3147+ <reference key="source" ref="920214336"/>
3148+ <reference key="destination" ref="676631602"/>
3149+ </object>
3150+ <int key="connectionID">652</int>
3151+ </object>
3152+ <object class="IBConnectionRecord">
3153+ <object class="IBOutletConnection" key="connection">
3154+ <string key="label">_mainWindow</string>
3155+ <reference key="source" ref="920214336"/>
3156+ <reference key="destination" ref="972006081"/>
3157+ </object>
3158+ <int key="connectionID">653</int>
3159+ </object>
3160+ <object class="IBConnectionRecord">
3161+ <object class="IBOutletConnection" key="connection">
3162+ <string key="label">_mainController</string>
3163+ <reference key="source" ref="943689817"/>
3164+ <reference key="destination" ref="690852348"/>
3165+ </object>
3166+ <int key="connectionID">655</int>
3167+ </object>
3168+ <object class="IBConnectionRecord">
3169+ <object class="IBOutletConnection" key="connection">
3170+ <string key="label">_undoManager</string>
3171+ <reference key="source" ref="690852348"/>
3172+ <reference key="destination" ref="943689817"/>
3173+ </object>
3174+ <int key="connectionID">656</int>
3175+ </object>
3176+ <object class="IBConnectionRecord">
3177+ <object class="IBOutletConnection" key="connection">
3178+ <string key="label">_undoManager</string>
3179+ <reference key="source" ref="986578374"/>
3180+ <reference key="destination" ref="943689817"/>
3181+ </object>
3182+ <int key="connectionID">657</int>
3183+ </object>
3184+ <object class="IBConnectionRecord">
3185+ <object class="IBActionConnection" key="connection">
3186+ <string key="label">undo:</string>
3187+ <reference key="source" ref="690852348"/>
3188+ <reference key="destination" ref="1058277027"/>
3189+ </object>
3190+ <int key="connectionID">658</int>
3191+ </object>
3192+ <object class="IBConnectionRecord">
3193+ <object class="IBActionConnection" key="connection">
3194+ <string key="label">redo:</string>
3195+ <reference key="source" ref="690852348"/>
3196+ <reference key="destination" ref="790794224"/>
3197+ </object>
3198+ <int key="connectionID">659</int>
3199+ </object>
31283200 </object>
31293201 <object class="IBMutableOrderedSet" key="objectRecords">
31303202 <object class="NSArray" key="orderedObjects">
@@ -4541,6 +4613,16 @@
45414613 <reference key="object" ref="387527700"/>
45424614 <reference key="parent" ref="110575045"/>
45434615 </object>
4616+ <object class="IBObjectRecord">
4617+ <int key="objectID">647</int>
4618+ <reference key="object" ref="920214336"/>
4619+ <reference key="parent" ref="0"/>
4620+ </object>
4621+ <object class="IBObjectRecord">
4622+ <int key="objectID">654</int>
4623+ <reference key="object" ref="943689817"/>
4624+ <reference key="parent" ref="0"/>
4625+ </object>
45444626 </object>
45454627 </object>
45464628 <object class="NSMutableDictionary" key="flattenedProperties">
@@ -4800,6 +4882,10 @@
48004882 <string>58.ImportedFromIB2</string>
48014883 <string>580.IBPluginDependency</string>
48024884 <string>586.IBPluginDependency</string>
4885+ <string>586.IBViewIntegration.shadowBlurRadius</string>
4886+ <string>586.IBViewIntegration.shadowColor</string>
4887+ <string>586.IBViewIntegration.shadowOffsetHeight</string>
4888+ <string>586.IBViewIntegration.shadowOffsetWidth</string>
48034889 <string>587.IBPluginDependency</string>
48044890 <string>588.IBPluginDependency</string>
48054891 <string>589.IBPluginDependency</string>
@@ -4910,7 +4996,7 @@
49104996 <integer value="1"/>
49114997 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
49124998 <integer value="1"/>
4913- <string>{{202, 620}, {254, 303}}</string>
4999+ <string>{{258, 724}, {254, 303}}</string>
49145000 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
49155001 <integer value="1"/>
49165002 <string>{{187, 434}, {243, 243}}</string>
@@ -5107,6 +5193,10 @@
51075193 <integer value="1"/>
51085194 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
51095195 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
5196+ <real value="0.0"/>
5197+ <reference ref="666650852"/>
5198+ <real value="0.0"/>
5199+ <real value="0.0"/>
51105200 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
51115201 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
51125202 <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
@@ -5176,7 +5266,7 @@
51765266 </object>
51775267 </object>
51785268 <nil key="sourceID"/>
5179- <int key="maxID">646</int>
5269+ <int key="maxID">659</int>
51805270 </object>
51815271 <object class="IBClassDescriber" key="IBDocument.Classes">
51825272 <object class="NSMutableArray" key="referencedPartialClassDescriptions">
@@ -5193,12 +5283,14 @@
51935283 <string>openProjectLoadDialog:</string>
51945284 <string>openProjectSaveDialog:</string>
51955285 <string>recordingStateChanged:</string>
5286+ <string>redo:</string>
51965287 <string>removeAllKeyFrame:</string>
51975288 <string>removeEffect:</string>
51985289 <string>rewriteProject:</string>
51995290 <string>startPlay:</string>
52005291 <string>stopPlay:</string>
52015292 <string>timeSliderChanged:</string>
5293+ <string>undo:</string>
52025294 <string>writeToFile:</string>
52035295 </object>
52045296 <object class="NSMutableArray" key="dict.values">
@@ -5215,6 +5307,8 @@
52155307 <string>id</string>
52165308 <string>id</string>
52175309 <string>id</string>
5310+ <string>id</string>
5311+ <string>id</string>
52185312 </object>
52195313 </object>
52205314 <object class="NSMutableDictionary" key="outlets">
@@ -5225,6 +5319,7 @@
52255319 <string>_mainWindow</string>
52265320 <string>_tableController</string>
52275321 <string>_timeLineController</string>
5322+ <string>_undoManager</string>
52285323 <string>_writer</string>
52295324 <string>timeCodeField</string>
52305325 <string>timeSlider</string>
@@ -5235,7 +5330,8 @@
52355330 <string>NSWindow</string>
52365331 <string>ElisPropertyTableController</string>
52375332 <string>ElisTimeLineController</string>
5238- <string>ElisWriter</string>
5333+ <string>ElisUndoManager</string>
5334+ <string>id</string>
52395335 <string>NSTextField</string>
52405336 <string>NSSlider</string>
52415337 </object>
@@ -5334,12 +5430,14 @@
53345430 <string>_mainController</string>
53355431 <string>_tableController</string>
53365432 <string>_timeLineView</string>
5433+ <string>_undoManager</string>
53375434 </object>
53385435 <object class="NSMutableArray" key="dict.values">
53395436 <bool key="EncodedWithXMLCoder">YES</bool>
53405437 <string>id</string>
53415438 <string>id</string>
53425439 <string>id</string>
5440+ <string>id</string>
53435441 </object>
53445442 </object>
53455443 <object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -5356,11 +5454,13 @@
53565454 <bool key="EncodedWithXMLCoder">YES</bool>
53575455 <string>_mainController</string>
53585456 <string>_timeLineController</string>
5457+ <string>_undoManager</string>
53595458 </object>
53605459 <object class="NSMutableArray" key="dict.values">
53615460 <bool key="EncodedWithXMLCoder">YES</bool>
53625461 <string>id</string>
53635462 <string>id</string>
5463+ <string>id</string>
53645464 </object>
53655465 </object>
53665466 <object class="IBClassDescriptionSource" key="sourceIdentifier">
@@ -5369,6 +5469,18 @@
53695469 </object>
53705470 </object>
53715471 <object class="IBPartialClassDescription">
5472+ <string key="className">ElisUndoManager</string>
5473+ <string key="superclassName">NSObject</string>
5474+ <object class="NSMutableDictionary" key="outlets">
5475+ <string key="NS.key.0">_mainController</string>
5476+ <string key="NS.object.0">id</string>
5477+ </object>
5478+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
5479+ <string key="majorKey">IBProjectSource</string>
5480+ <string key="minorKey">ElisUndoManager.h</string>
5481+ </object>
5482+ </object>
5483+ <object class="IBPartialClassDescription">
53725484 <string key="className">ElisWriter</string>
53735485 <string key="superclassName">NSObject</string>
53745486 <object class="NSMutableDictionary" key="outlets">
@@ -5396,6 +5508,33 @@
53965508 </object>
53975509 </object>
53985510 <object class="IBPartialClassDescription">
5511+ <string key="className">ElisWriterLegacy</string>
5512+ <string key="superclassName">NSObject</string>
5513+ <object class="NSMutableDictionary" key="outlets">
5514+ <bool key="EncodedWithXMLCoder">YES</bool>
5515+ <object class="NSArray" key="dict.sortedKeys">
5516+ <bool key="EncodedWithXMLCoder">YES</bool>
5517+ <string>_bar</string>
5518+ <string>_barSheet</string>
5519+ <string>_mainController</string>
5520+ <string>_mainView</string>
5521+ <string>_mainWindow</string>
5522+ </object>
5523+ <object class="NSMutableArray" key="dict.values">
5524+ <bool key="EncodedWithXMLCoder">YES</bool>
5525+ <string>id</string>
5526+ <string>id</string>
5527+ <string>id</string>
5528+ <string>id</string>
5529+ <string>id</string>
5530+ </object>
5531+ </object>
5532+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
5533+ <string key="majorKey">IBProjectSource</string>
5534+ <string key="minorKey">ElisWriterLegacy.h</string>
5535+ </object>
5536+ </object>
5537+ <object class="IBPartialClassDescription">
53995538 <string key="className">Elis_ColorsAppDelegate</string>
54005539 <string key="superclassName">NSObject</string>
54015540 <object class="NSMutableDictionary" key="outlets">
Show on old repository browser