]> git.sesse.net Git - vlc/blob - projects/macosx/vlc_app/Sources/VLCMediaLayer.m
Rework of vout_OSDEpg.
[vlc] / projects / macosx / vlc_app / Sources / VLCMediaLayer.m
1 //
2 //  VLCMediaLayer.m
3 //  VLC
4 //
5 //  Created by Pierre d'Herbemont on 1/14/08.
6 //  Copyright 2008 __MyCompanyName__. All rights reserved.
7 //
8
9 #import "VLCMediaLayer.h"
10
11 /*****************************************************************************
12  * Some configuration first. Defines the size of the artwork layer.
13  */
14 static CGSize kArtworkSize = { 256., 256. };
15
16 /*****************************************************************************
17  * @interface VLCMediaLayer (Private)
18  */
19
20 @interface VLCMediaLayer (Private)
21 - (void)updateSublayers;
22 @end
23
24 /*****************************************************************************
25  * @interface VLCMediaLayer ()
26  */
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;
33 @end
34
35 /*****************************************************************************
36  * @implementation VLCMediaLayer
37  */
38 @implementation VLCMediaLayer
39 @synthesize displayFullInformation;
40 @synthesize media;
41 @synthesize titleLayer;
42 @synthesize genreLayer;
43 @synthesize artistLayer;
44 @synthesize artworkLayer;
45
46 + (id)layer
47 {
48     return [self layerWithMedia:[VLCMedia mediaAsNodeWithName:@"Empty Media"]];
49 }
50 + (id)layerWithMedia:(VLCMedia *)aMedia
51 {
52     VLCMediaLayer * me = [super layer];
53
54     if(!me) return nil;
55
56     me.media = aMedia;
57     me.displayFullInformation = YES;
58
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",
73                                         nil];
74     NSDictionary * textTitleStyle = [NSDictionary dictionaryWithObjectsAndKeys:
75                                         [NSNumber numberWithInteger:12], @"cornerRadius",
76                                         [NSValue valueWithSize:NSMakeSize(5, 0)], @"margin",
77                                         @"Lucida", @"font",
78                                         [NSNumber numberWithInteger:26], @"fontSize",
79                                         [NSNumber numberWithFloat: .7], @"shadowOpacity",
80                                         [NSNumber numberWithFloat: 3.], @"shadowRadius",
81                                         kCAAlignmentLeft, @"alignmentMode",
82                                         nil];
83     /* First off, text */
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.]];
102
103
104     [textLayer addSublayer:me.titleLayer];
105     [textLayer addSublayer:me.artistLayer];
106     [textLayer addSublayer:me.genreLayer];
107     textLayer.contentsGravity = kCAGravityCenter;
108     textLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
109
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;
115
116    // me.artworkLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
117     textLayer.frame = CGRectMake(0.,0., kArtworkSize.width, kArtworkSize.height);
118
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];
125
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]];
131
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]];
136         
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]];
140
141     me.artworkLayer.zPosition = -30.f;
142
143     me.artworkLayer.shadowOpacity = .3;
144     me.artworkLayer.shadowRadius = 10.;
145     static CATransform3D rot, projection;
146     static BOOL transformInited = NO;
147     if( !transformInited )
148     {
149         rot = CATransform3DMakeRotation(.1
150         , 0., 1., 0.);
151             projection = CATransform3DIdentity; 
152         projection.m34 = 1. / -80.;
153         transformInited = YES;
154     }
155     me.artworkLayer.transform = rot;
156     container.sublayerTransform = projection;
157
158     me.layoutManager = [CAConstraintLayoutManager layoutManager];
159     [me addSublayer:textLayer];
160     [me addSublayer:container];
161
162     [me updateSublayers];
163
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];
169
170     return me;
171 }
172
173 - (void)dealloc
174 {
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"];
180
181     [super dealloc];
182 }
183 @end
184
185 /*****************************************************************************
186  * @implementation VLCMediaLayer (Private)
187  */
188 @implementation VLCMediaLayer (Private)
189
190 - (void)updateSublayers
191 {
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"] )
199     {
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;
204     }
205     [CATransaction commit];
206 }
207
208 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
209 {
210     if( [keyPath hasPrefix:@"metaDictionary"] )
211     {
212         [self updateSublayers];
213         return;
214     }
215     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
216 }
217 @end