5 // Created by Pierre d'Herbemont on 1/14/08.
6 // Copyright 2008 __MyCompanyName__. All rights reserved.
9 #import "VLCMediaLayer.h"
11 /*****************************************************************************
12 * Some configuration first. Defines the size of the artwork layer.
14 static CGSize kArtworkSize = { 256., 256. };
16 /*****************************************************************************
17 * @interface VLCMediaLayer (Private)
20 @interface VLCMediaLayer (Private)
21 - (void)updateSublayers;
24 /*****************************************************************************
25 * @interface VLCMediaLayer ()
27 @interface VLCMediaLayer ()
28 @property (retain,readwrite) VLCMedia * media;
29 @property (retain,readwrite) CATextLayer * titleLayer;
30 @property (retain,readwrite) CATextLayer * artistLayer;
31 @property (retain,readwrite) CATextLayer * genreLayer;
32 @property (retain,readwrite) CALayer * artworkLayer;
35 /*****************************************************************************
36 * @implementation VLCMediaLayer
38 @implementation VLCMediaLayer
39 @synthesize displayFullInformation;
41 @synthesize titleLayer;
42 @synthesize genreLayer;
43 @synthesize artistLayer;
44 @synthesize artworkLayer;
48 return [self layerWithMedia:[VLCMedia mediaAsNodeWithName:@"Empty Media"]];
50 + (id)layerWithMedia:(VLCMedia *)aMedia
52 VLCMediaLayer * me = [super layer];
57 me.displayFullInformation = YES;
59 /* Set the default layout */
60 me.titleLayer = [CATextLayer layer];
61 me.artistLayer = [CATextLayer layer];
62 me.genreLayer = [CATextLayer layer];
63 CALayer * textLayer = [CALayer layer];
64 NSDictionary * textStyle = [NSDictionary dictionaryWithObjectsAndKeys:
65 [NSNumber numberWithInteger:12], @"cornerRadius",
66 [NSValue valueWithSize:NSMakeSize(5, 0)], @"margin",
67 @"Lucida-Bold", @"font",
68 CGColorCreateGenericGray(0.5, 1.),@"foregroundColor",
69 [NSNumber numberWithInteger:18], @"fontSize",
70 [NSNumber numberWithFloat: .8], @"shadowOpacity",
71 [NSNumber numberWithFloat: 1.], @"shadowRadius",
72 kCAAlignmentLeft, @"alignmentMode",
74 NSDictionary * textTitleStyle = [NSDictionary dictionaryWithObjectsAndKeys:
75 [NSNumber numberWithInteger:12], @"cornerRadius",
76 [NSValue valueWithSize:NSMakeSize(5, 0)], @"margin",
78 [NSNumber numberWithInteger:26], @"fontSize",
79 [NSNumber numberWithFloat: .7], @"shadowOpacity",
80 [NSNumber numberWithFloat: 3.], @"shadowRadius",
81 kCAAlignmentLeft, @"alignmentMode",
84 me.titleLayer.style = textTitleStyle;
85 me.titleLayer.string = @"Title";
86 me.titleLayer.name = @"title";
87 [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX offset:0.]];
88 [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX offset:0.]];
89 [me.titleLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinY relativeTo:@"artist" attribute:kCAConstraintMaxY offset:10.]];
90 me.artistLayer.style = textStyle;
91 me.artistLayer.string = @"Artist";
92 me.artistLayer.name = @"artist";
93 [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"title" attribute:kCAConstraintMinX]];
94 [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"title" attribute:kCAConstraintMaxX]];
95 [me.artistLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
96 me.genreLayer.style = textStyle;
97 me.genreLayer.string = @"Genre";
98 me.genreLayer.name = @"genre";
99 [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"title" attribute:kCAConstraintMinX]];
100 [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"title" attribute:kCAConstraintMaxX]];
101 [me.genreLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxY relativeTo:@"artist" attribute:kCAConstraintMinY offset:-10.]];
104 [textLayer addSublayer:me.titleLayer];
105 [textLayer addSublayer:me.artistLayer];
106 [textLayer addSublayer:me.genreLayer];
107 textLayer.contentsGravity = kCAGravityCenter;
108 textLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
110 /* Empty layer for picture */
111 me.artworkLayer = [CALayer layer];
112 me.artworkLayer.backgroundColor = CGColorCreateGenericGray(0.5, 0.4);
113 me.artworkLayer.borderColor = CGColorCreateGenericRGB(1., 1., 1., .8);
114 me.artworkLayer.borderWidth = 3.0;
116 // me.artworkLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
117 textLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
119 /* Position the text and the artwork layer */
120 CALayer * container = [CALayer layer];
121 me.artworkLayer.name = @"artworkLayer";
122 textLayer.name = @"textLayer";
123 container.name = @"artContainer";
124 container.layoutManager = [CAConstraintLayoutManager layoutManager];
126 [container addSublayer:me.artworkLayer];
127 [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX offset:60.]];
128 [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]];
129 [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintHeight relativeTo:@"superlayer" attribute:kCAConstraintHeight scale:.6 offset:0.]];
130 [container addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMidX]];
132 [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"superlayer" attribute:kCAConstraintMinX]];
133 [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinY relativeTo:@"superlayer" attribute:kCAConstraintMinY]];
134 [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxY relativeTo:@"superlayer" attribute:kCAConstraintMaxY]];
135 [me.artworkLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX]];
137 [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX relativeTo:@"artContainer" attribute:kCAConstraintMaxX]];
138 [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX relativeTo:@"superlayer" attribute:kCAConstraintMaxX ]];
139 [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"artContainer" attribute:kCAConstraintMidY]];
141 me.artworkLayer.zPosition = -30.f;
143 me.artworkLayer.shadowOpacity = .3;
144 me.artworkLayer.shadowRadius = 10.;
145 static CATransform3D rot, projection;
146 static BOOL transformInited = NO;
147 if( !transformInited )
149 rot = CATransform3DMakeRotation(.1
151 projection = CATransform3DIdentity;
152 projection.m34 = 1. / -80.;
153 transformInited = YES;
155 me.artworkLayer.transform = rot;
156 container.sublayerTransform = projection;
158 me.layoutManager = [CAConstraintLayoutManager layoutManager];
159 [me addSublayer:textLayer];
160 [me addSublayer:container];
162 [me updateSublayers];
164 /* The following will trigger -observeValueForKeyPath: ofObject: change: context: */
165 [me.media addObserver:me forKeyPath:@"metaDictionary.title" options:NSKeyValueObservingOptionNew context:nil];
166 [me.media addObserver:me forKeyPath:@"metaDictionary.genre" options:NSKeyValueObservingOptionNew context:nil];
167 [me.media addObserver:me forKeyPath:@"metaDictionary.artist" options:NSKeyValueObservingOptionNew context:nil];
168 [me.media addObserver:me forKeyPath:@"metaDictionary.artwork" options:NSKeyValueObservingOptionNew context:nil];
175 /* Previously registered in +layerWithMediaArrayController: +layerWithMedia:*/
176 [self.media removeObserver:self forKeyPath:@"metaDictionary.title"];
177 [self.media removeObserver:self forKeyPath:@"metaDictionary.genre"];
178 [self.media removeObserver:self forKeyPath:@"metaDictionary.artist"];
179 [self.media removeObserver:self forKeyPath:@"metaDictionary.artwork"];
185 /*****************************************************************************
186 * @implementation VLCMediaLayer (Private)
188 @implementation VLCMediaLayer (Private)
190 - (void)updateSublayers
192 [CATransaction begin];
193 self.titleLayer.string = [self.media.metaDictionary objectForKey:@"title"];
194 NSString * artist = [self.media.metaDictionary objectForKey:@"artist"];
195 self.artistLayer.string = artist ? artist : @"No Artist";
196 NSString * genre = [self.media.metaDictionary objectForKey:@"genre"];
197 self.genreLayer.string = genre ? genre : @"No Genre";
198 if( [self.media valueForKeyPath:@"metaDictionary.artwork"] )
200 self.artworkLayer.contents = (id)[[self.media valueForKeyPath:@"metaDictionary.artwork"] CGImage];
201 self.artworkLayer.contentsGravity = kCAGravityResizeAspect;
202 self.artworkLayer.borderWidth = 0.;
203 self.artworkLayer.backgroundColor = nil;
205 [CATransaction commit];
208 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
210 if( [keyPath hasPrefix:@"metaDictionary"] )
212 [self updateSublayers];
215 [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];