OSDN Git Service

alpha2
[eliscolors/main.git] / ElisLayer.m
1 //  Copyright (c) 2009 Yanagi Asakura
2 //
3 //  This software is provided 'as-is', without any express or implied
4 //  warranty. In no event will the authors be held liable for any damages
5 //  arising from the use of this software.
6 //
7 //  Permission is granted to anyone to use this software for any purpose,
8 //  including commercial applications, and to alter it and redistribute it
9 //  freely, subject to the following restrictions:
10 //
11 //  1. The origin of this software must not be misrepresented; you must not
12 //  claim that you wrote the original software. If you use this software
13 //  in a product, an acknowledgment in the product documentation would be
14 //  appreciated but is not required.
15 //
16 //  2. Altered source versions must be plainly marked as such, and must not be
17 //  misrepresented as being the original software.
18 //
19 //  3. This notice may not be removed or altered from any source
20 //  distribution.
21
22 //
23 //  ElisLayer.m
24 //  Elis Colors
25 //
26 //  Created by 柳 on 09/09/12.
27 //  Copyright 2009 __MyCompanyName__. All rights reserved.
28 //
29
30 #import "ElisLayer.h"
31
32 #define TRACK_SIZE 32
33
34 static float convertQTTimeToSecond(QTTime t)
35 {
36     return (float)t.timeValue/t.timeScale;
37 }
38
39 @implementation ElisLayer
40
41 @synthesize media;
42
43 - (id)init
44 {
45     self.media = nil;
46 //    position.x = 0;
47 //    position.y = 0;
48     offset = QTZeroTime;
49     effects = [[NSMutableArray alloc] init];
50     pxKeyframe = [[ElisKeyframe alloc] init];
51     pyKeyframe = [[ElisKeyframe alloc] init];
52     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
53     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
54     
55     originSize = NSZeroRect;
56     
57     return self;
58 }
59
60 - (void)setMedia:(ElisMedia *)m
61 {
62     media = m;
63     if([[m type] isEqualToString:@"sound"]){
64         volumeKeyframe = [[ElisKeyframe alloc] init];
65         [volumeKeyframe setValueForTime:0.3 time:QTZeroTime];
66     }
67     else{
68         volumeKeyframe = nil;
69         [self addEffect:@"CIOpacity"]; //デフォルトで透過度フィルタと
70         [self addEffect:@"CIAffineTransform"]; // アフィン変換フィルタはつけておく。
71     }
72 }
73
74 - (void)setAlayer:(CALayer *)layer
75 {
76     alayer = layer;
77     
78     [layer setValue:self forKey:@"ElisLayer"];
79     
80     // layer.frameをバインド。
81     [layer addObserver:self 
82             forKeyPath:@"frame" 
83                options:(NSKeyValueObservingOptionNew) 
84                context:NULL];
85     
86     originSize = [media size];
87 }
88
89 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
90 {
91     [self changeMapping];
92 }
93
94 - (void)addEffect:(NSString*)name
95 {
96     ElisEffect* e = [[ElisEffect alloc] initWithName:name];
97     if(e)
98         [effects addObject:e];
99 }
100
101 // mappingとtrackNumberを変化させる。
102 - (void)changeMapping
103 {
104     CGRect frame = alayer.frame;
105     QTTime begin = QTMakeTime(frame.origin.x*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
106     QTTime d = QTMakeTime(frame.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
107     
108 //    trackNumber = floor((frame.origin.y+1)/51.0);
109     trackNumber = round((floor(frame.origin.y/51.0) * 51 + 1 + 25)/51.0);
110     mapping = QTMakeTimeRange(begin, d);
111     
112     int i, center = frame.origin.y + frame.size.height/2;
113     for(i = 0; i < TRACK_SIZE; i++){ // これしきのことにループ回すってどういうことなの...
114         if(51.0*i+1 <= center && center <= 51.0*(i+1)+1){
115             trackNumber = i;
116             return;
117         }
118     }
119 }
120
121 - (void)changeOffset:(float)df
122 {
123     QTTime new_offset = QTTimeIncrement(offset, QTMakeTime(df*DEFAULT_FPS/timeLineScale, DEFAULT_FPS));
124     
125     offset = new_offset;
126 }
127
128 - (BOOL)canChangeMapping:(CGRect)rect
129 {
130     QTTime duration;
131     
132     if([[media type] isEqualToString:@"image"] || [[media type] isEqualToString:@"text"] || [media isQuartz])
133         duration = QTMakeTime(60*10, 1);
134     else
135         duration = [media duration];
136     
137     QTTime wantDuration = QTMakeTime(rect.size.width*DEFAULT_FPS/timeLineScale, DEFAULT_FPS);
138     float d = convertQTTimeToSecond(duration) - convertQTTimeToSecond(offset);
139     float wd = convertQTTimeToSecond(wantDuration);
140     
141     return 0.5 <= wd && wd <= d;
142 }
143
144 - (BOOL)canChangeOffset:(float)df
145 {
146     float now_offset = convertQTTimeToSecond(offset);
147     float duration = convertQTTimeToSecond([media duration]);
148     df /= timeLineScale;
149     
150     return 0.0 <= df + now_offset && df + now_offset <= duration;
151 }
152
153 - (BOOL)isInclude:(QTTime)time
154 {
155     float t = convertQTTimeToSecond(time);
156     float begin = convertQTTimeToSecond(mapping.time);
157     return begin <= t && t <= begin + convertQTTimeToSecond(mapping.duration);
158 //    return QTTimeInTimeRange(time, mapping); // これだとマルチスレッドにできなくね?
159 }
160
161 - (int)trackNumber
162 {
163     return trackNumber;
164 }
165
166 - (ElisLayer*)cutAtTime:(QTTime)cutTime
167 {
168     QTTime innerCutTime = [self convertToInnnerTime:cutTime];
169     ElisLayer* new;
170     NSKeyedArchiver* corder;
171     NSKeyedUnarchiver* decoder;
172     NSMutableData* data = [NSMutableData data];
173     
174     corder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
175     [self encodeWithCoder:corder];
176     [corder finishEncoding];
177     
178     new = [ElisLayer alloc];
179     decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
180     new = [new initWithCoder:decoder];
181     [decoder finishDecoding];
182     
183     mapping.duration = QTTimeDecrement(mapping.duration, cutTime);
184     [self setLayer:alayer];
185     
186     [new cutBack:innerCutTime];
187     return new;
188 }
189
190 - (void)cutBack:(QTTime)time
191 {
192     offset = time;
193     mapping.time = time;
194     mapping.duration = QTTimeDecrement(mapping.duration, time);
195     [self setLayer:alayer];
196 }
197
198 - (CALayer*)alayer
199 {
200     return alayer;
201 }
202
203 - (void)setPositionX:(float)x forTime:(QTTime)time
204 {
205     if(recording)
206         [pxKeyframe setValueForTime:x time:time];
207     else
208         [pxKeyframe setValueForTime:x time:QTZeroTime];
209 }
210
211 - (void)setPositionY:(float)y forTime:(QTTime)time
212 {
213     if(recording)
214         [pyKeyframe setValueForTime:y time:time];
215     else 
216         [pyKeyframe setValueForTime:y time:QTZeroTime];
217 }
218
219 - (CIImage*)getEffectedImage:(CVTimeStamp*)timeStamp forTime:(QTTime)time
220 {
221     QTTime innerTime = QTTimeDecrement(time, mapping.time);
222     CIImage* image;
223     if(usingStampMode){
224         image = [media getFrameForTime:timeStamp];
225     }else{
226         [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
227         image = [media getFrameForTime:nil];
228     }
229     if(image == nil){
230         [media setVolume:[volumeKeyframe getValueForTime:QTTimeIncrement(innerTime, offset)]];
231         return nil;
232     }
233     
234     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];
235 }
236
237 - (CIImage*)getEffectedImageWithoutStamp:(QTTime)time
238 {
239     QTTime innerTime = QTTimeDecrement(time, mapping.time);
240     [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
241     CIImage* image = [media getFrameForTime:nil];
242     if(image == nil){
243         [media setVolume:[volumeKeyframe getValueForTime:QTTimeIncrement(innerTime, offset)]];
244         return nil;
245     }
246     
247     return [self applyEffects:image forTime:QTTimeIncrement(innerTime, offset)];    
248 }
249
250 - (CIImage*)applyEffects:(CIImage*)image forTime:(QTTime)time
251 {
252     int i, size = [effects count];
253     ElisEffect* ef;
254     
255     for(i = 0; i < size; i++){
256         ef = [effects objectAtIndex:i];
257         [ef setInputImage:image];
258         image = [ef getImage:time];
259     }
260     
261     return image;
262 }    
263
264 - (NSPoint)getPositionForTime:(QTTime)time
265 {
266     float x = [pxKeyframe getValueForTime:time];
267     float y = [pyKeyframe getValueForTime:time];
268     
269     return NSMakePoint(x, y);
270 }
271
272 - (float)getVolumeForTime:(QTTime)time
273 {
274     return [volumeKeyframe getValueForTime:QTTimeIncrement(QTTimeDecrement(time, mapping.time), offset)];
275 }
276
277 - (float)getVolumeForInnerTime:(QTTime)time
278 {
279    return [volumeKeyframe getValueForTime:time];
280 }
281
282 - (void)play
283 {
284     [media play];
285 }
286
287 - (void)stop
288 {
289     [media stop];
290 }
291
292 - (void)releaseContext
293 {
294     [media releaseContext];
295 }
296
297 - (QTTimeRange)mapping
298 {
299     return mapping;
300 }
301
302 - (void)seek:(QTTime)time
303 {
304     if([self isInclude:time]){
305         QTTime innerTime = QTTimeDecrement(time, mapping.time); // レイヤー内相対時間へ変換
306         [media setCurrentTime:QTTimeIncrement(innerTime, offset)];
307     } else {
308         [media setCurrentTime:offset];
309     }
310 }
311
312
313 // for Property Table
314 - (void)createPropertyTableDataSource:(NSMutableArray*)t_effects
315                              property:(NSMutableArray*)t_propertyNames
316                                 value:(NSMutableArray*)t_valueNames
317 {
318     NSMutableDictionary* params;
319     NSArray* arr;
320     NSString* paramName, *effectName;
321     NSDictionary* dict;
322     
323     if(![[media type] isEqualToString:@"sound"]){
324     [t_propertyNames addObject:@"Position X"];
325     [t_effects addObject:self];
326     [t_valueNames addObject:@""];
327     [t_propertyNames addObject:@"Position Y"];
328     [t_effects addObject:self];
329     [t_valueNames addObject:@""];
330     
331     int i, size = [effects count];
332     for(i = 0; i < size; i++){
333         params = [[effects objectAtIndex:i] getParamDictionary];
334         arr = [params allKeys];
335         arr = [arr sortedArrayUsingSelector:@selector(compare:)];
336         effectName = [[effects objectAtIndex:i] getName];
337         for(paramName in arr){
338             [t_propertyNames addObject:[NSString stringWithFormat:@"%@ %@", effectName, [paramName substringFromIndex:5]]];
339             [t_effects addObject:[effects objectAtIndex:i]];
340             [t_valueNames addObject:paramName];
341         }
342     }
343     }else{
344         [t_propertyNames addObject:@"Volume"];
345         [t_effects addObject:self];
346         [t_valueNames addObject:@""];
347     }
348 }
349
350 - (QTTime)convertToInnnerTime:(QTTime)globalTime
351 {
352     return QTTimeIncrement(QTTimeDecrement(globalTime, mapping.time), offset);
353 }
354
355 - (QTTime)plusOffsetTime:(QTTime)time
356 {
357     return QTTimeIncrement(time, offset);
358 }
359
360 - (void)finalize
361 {
362     [alayer removeObserver:self forKeyPath:@"frame"];
363     [super finalize];
364 }
365
366 - (void)removePositionXKeyframe
367 {
368     pxKeyframe = [[ElisKeyframe alloc] init];
369     [pxKeyframe setValueForTime:0.0 time:QTZeroTime];
370 }
371
372 - (void)removePositionYKerframe
373 {
374     pyKeyframe = [[ElisKeyframe alloc] init];
375     [pyKeyframe setValueForTime:0.0 time:QTZeroTime];
376 }
377
378 - (void)removeVolumeKeyframe
379 {
380     volumeKeyframe = [[ElisKeyframe alloc] init];
381     [volumeKeyframe setValueForTime:0.3 time:QTZeroTime];
382 }
383
384 - (void)removeEffect:(ElisEffect*)ef
385 {
386     [effects removeObject:ef];
387 }
388
389 - (void)getSoundTrack:(NSMutableArray*)soundTrack
390 {
391     QTTrack* t;
392     QTTime qtr;
393     t = [media getSoundTrack];
394     if(t){
395         [(QTMovie*)[media getSoundMovie] setAttribute:[NSNumber numberWithBool:YES] forKey:QTMovieEditableAttribute];
396         qtr = [media duration];
397         mapping.time = QTMakeTime(convertQTTimeToSecond(mapping.time)*qtr.timeScale, qtr.timeScale);
398         mapping.duration = QTMakeTime(convertQTTimeToSecond(mapping.duration)*qtr.timeScale, qtr.timeScale);
399         [[media getSoundMovie] deleteSegment:QTMakeTimeRange(QTZeroTime, offset)];
400         [[media getSoundMovie] insertEmptySegmentAt:QTMakeTimeRange(QTZeroTime, mapping.time)];
401 //        [[media getSoundMovie] scaleSegment:qtr newDuration:QTMakeTimeRange(offset, mapping.duration)];
402         [soundTrack addObject:[media getSoundMovie]];
403         [soundTrack addObject:t];
404         [soundTrack addObject:[NSValue valueWithQTTime:QTTimeIncrement(mapping.duration, mapping.time)]];
405 //        [soundTrack addObject:[NSValue valueWithQTTime:offset]];
406 //        [soundTrack addObject:[NSValue valueWithQTTimeRange:mapping]];
407     }
408 }
409
410 - (void)encodeWithCoder:(NSCoder*)encoder
411 {
412     [encoder encodeObject:media forKey:@"media"];
413     [encoder encodeInt:trackNumber forKey:@"trackNumber"];
414     [encoder encodeObject:QTStringFromTimeRange(mapping) forKey:@"mapping"];
415     [encoder encodeObject:QTStringFromTime(offset) forKey:@"offset"];
416     [encoder encodeObject:effects forKey:@"effects"];
417     [encoder encodeObject:pxKeyframe forKey:@"pxKeyframe"];
418     [encoder encodeObject:pyKeyframe forKey:@"pyKeyframe"];
419     [encoder encodeObject:volumeKeyframe forKey:@"volumeKeyframe"];
420 }
421
422 - (id)initWithCoder:(NSCoder*)coder
423 {
424     media = [coder decodeObjectForKey:@"media"];
425     trackNumber = [coder decodeIntForKey:@"trackNumber"];
426     mapping = QTTimeRangeFromString([coder decodeObjectForKey:@"mapping"]);
427     offset = QTTimeFromString([coder decodeObjectForKey:@"offset"]);
428     effects = [coder decodeObjectForKey:@"effects"];
429     pxKeyframe = [coder decodeObjectForKey:@"pxKeyframe"];
430     pyKeyframe = [coder decodeObjectForKey:@"pyKeyframe"];
431     volumeKeyframe = [coder decodeObjectForKey:@"volumeKeyframe"];
432     
433     return self;
434 }
435
436 - (void)saveToEncoder:(NSCoder*)encoder
437 {
438     [encoder encodeInt:trackNumber forKey:@"trackNumber"];
439     [encoder encodeObject:QTStringFromTimeRange(mapping) forKey:@"mapping"];
440     [encoder encodeObject:QTStringFromTime(offset) forKey:@"offset"];
441     [encoder encodeObject:effects forKey:@"effects"];
442     [encoder encodeObject:pxKeyframe forKey:@"pxKeyframe"];
443     [encoder encodeObject:pyKeyframe forKey:@"pyKeyframe"];
444     [encoder encodeObject:volumeKeyframe forKey:@"volumeKeyframe"];
445     [encoder encodeFloat:[media speed] forKey:@"speed"];
446 }
447
448 - (void)loadFromDecoder:(NSCoder*)coder
449 {
450     trackNumber = [coder decodeIntForKey:@"trackNumber"];
451     mapping = QTTimeRangeFromString([coder decodeObjectForKey:@"mapping"]);
452     offset = QTTimeFromString([coder decodeObjectForKey:@"offset"]);
453     effects = [coder decodeObjectForKey:@"effects"];
454     pxKeyframe = [coder decodeObjectForKey:@"pxKeyframe"];
455     pyKeyframe = [coder decodeObjectForKey:@"pyKeyframe"];
456     [media setSpeed:[coder decodeFloatForKey:@"speed"]];
457     volumeKeyframe = [coder decodeObjectForKey:@"volumeKeyframe"];
458     
459     [self setLayer:alayer];
460 }
461
462 - (void)setLayer:(CALayer*)layer
463 {
464     layer.frame = CGRectMake(convertQTTimeToSecond(mapping.time)*timeLineScale, trackNumber*51+1,
465                              (/*convertQTTimeToSecond(mapping.time) + */convertQTTimeToSecond(mapping.duration))*timeLineScale, 50);
466     [self setAlayer:layer];
467 }
468
469 - (float)duration
470 {
471     return convertQTTimeToSecond(mapping.time) + convertQTTimeToSecond(mapping.duration);
472 }
473
474 - (NSString*)getPath
475 {
476     return [[media path] lastPathComponent];
477 }
478
479 - (NSString*)getType
480 {
481     return [media type];
482 }
483
484 - (NSString*)printName
485 {
486     if([[media type] isEqualToString:@"text"])
487         return @"text";
488     
489     return [self getPath];
490 }
491
492 - (NSSize)originSize
493 {
494     return originSize.size;
495 }
496
497 - (float)speed
498 {
499     return [media speed];
500 }
501
502 - (void)setSpeed:(float)s
503 {
504     if(s < 0.01 || s > 100.0) return;
505     [media setSpeed:s];
506     mapping.duration = [media duration];
507     [self setLayer:alayer];
508 }
509
510 - (void)setVolume:(float)v forTime:(QTTime)time
511 {
512     if(recording)
513         [volumeKeyframe setValueForTime:v time:time];
514     else
515         [volumeKeyframe setValueForTime:v time:QTZeroTime];
516 }
517
518 @end