Mercurial > mplayer.hg
annotate libvo/vo_macosx.m @ 19170:7e689bb31c07
Add simple edit list support to mov demuxer, it supports delay of audio and video tracks at the beginning of the file. E.g. video starts at 0.0s audio at 4.0s. It uses mplayers a/v-delay to achieve sync so please use with -framedrop for fastest sync. More Details in my mail to dev-eng from 2006-07-22.
author | atmos4 |
---|---|
date | Sun, 23 Jul 2006 22:34:02 +0000 |
parents | 3bf0d70b4c7f |
children | dd05dd9e3e7b |
rev | line source |
---|---|
15289 | 1 /* |
2 vo_macosx.m | |
3 by Nicolas Plourde <nicolasplourde@gmail.com> | |
4 | |
5 MPlayer Mac OSX video out module. | |
6 Copyright (c) Nicolas Plourde - 2005 | |
7 */ | |
8 | |
9 #import "vo_macosx.h" | |
16385 | 10 #include <sys/types.h> |
11 #include <sys/ipc.h> | |
12 #include <sys/shm.h> | |
15289 | 13 |
14 //MPLAYER | |
15 #include "config.h" | |
16 #include "fastmemcpy.h" | |
17 #include "video_out.h" | |
18 #include "video_out_internal.h" | |
19 #include "aspect.h" | |
20 #include "mp_msg.h" | |
21 #include "m_option.h" | |
22 | |
23 #include "input/input.h" | |
24 #include "input/mouse.h" | |
25 | |
26 #include "osdep/keycodes.h" | |
27 | |
28 //Cocoa | |
16385 | 29 NSProxy *mplayerosxProxy; |
15611 | 30 MPlayerOpenGLView *mpGLView; |
15289 | 31 NSAutoreleasePool *autoreleasepool; |
32 OSType pixelFormat; | |
33 | |
16385 | 34 //shared memory |
35 int shm_id; | |
36 struct shmid_ds shm_desc; | |
37 BOOL shared_buffer = false; | |
38 | |
15728 | 39 //Screen |
40 int screen_id; | |
41 BOOL screen_force; | |
42 NSRect screen_frame; | |
43 NSScreen *screen_handle; | |
44 NSArray *screen_array; | |
15289 | 45 |
46 //image | |
47 unsigned char *image_data; | |
48 static uint32_t image_width; | |
49 static uint32_t image_height; | |
50 static uint32_t image_depth; | |
51 static uint32_t image_bytes; | |
52 static uint32_t image_format; | |
53 | |
54 //vo | |
55 extern int vo_rootwin; | |
56 extern int vo_ontop; | |
57 extern int vo_fs; | |
58 static int isFullscreen; | |
15320 | 59 static int isOntop; |
15327 | 60 static int isRootwin; |
15289 | 61 extern float monitor_aspect; |
62 extern int vo_keepaspect; | |
63 extern float movie_aspect; | |
64 static float old_movie_aspect; | |
65 extern float vo_panscan; | |
66 | |
15731 | 67 static float winAlpha = 1; |
15289 | 68 static int int_pause = 0; |
69 | |
70 static vo_info_t info = | |
71 { | |
72 "Mac OSX Core Video", | |
73 "macosx", | |
74 "Nicolas Plourde <nicolas.plourde@gmail.com>", | |
75 "" | |
76 }; | |
77 | |
78 LIBVO_EXTERN(macosx) | |
79 | |
80 extern void mplayer_put_key(int code); | |
81 extern void vo_draw_text(int dxs,int dys,void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); | |
82 | |
83 static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride) | |
84 { | |
85 switch (image_format) | |
86 { | |
87 case IMGFMT_RGB32: | |
88 vo_draw_alpha_rgb32(w,h,src,srca,stride,image_data+4*(y0*image_width+x0),4*image_width); | |
89 break; | |
90 case IMGFMT_YUY2: | |
91 vo_draw_alpha_yuy2(w,h,src,srca,stride,image_data + (x0 + y0 * image_width) * 2,image_width*2); | |
92 break; | |
93 } | |
94 } | |
95 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
96 static int config(uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, char *title, uint32_t format) |
15289 | 97 { |
98 int i; | |
16385 | 99 |
15728 | 100 //init screen |
101 screen_array = [NSScreen screens]; | |
102 if(screen_id < [screen_array count]) | |
15289 | 103 { |
15728 | 104 screen_handle = [screen_array objectAtIndex:screen_id]; |
15289 | 105 } |
15728 | 106 else |
107 { | |
108 mp_msg(MSGT_VO, MSGL_FATAL, "Get device error: Device ID %d do not exist, falling back to main device.\n", screen_id); | |
109 screen_handle = [screen_array objectAtIndex:0]; | |
110 screen_id = 0; | |
111 } | |
112 screen_frame = [screen_handle frame]; | |
16385 | 113 |
15289 | 114 //misc mplayer setup |
115 image_width = width; | |
116 image_height = height; | |
117 switch (image_format) | |
118 { | |
119 case IMGFMT_BGR32: | |
120 case IMGFMT_RGB32: | |
121 image_depth = 32; | |
122 break; | |
16385 | 123 case IMGFMT_YUY2: |
15289 | 124 image_depth = 16; |
125 break; | |
126 } | |
127 image_bytes = (image_depth + 7) / 8; | |
18878 | 128 image_data = malloc(image_width*image_height*image_bytes); |
16385 | 129 |
130 if(!shared_buffer) | |
131 { | |
132 monitor_aspect = (float)screen_frame.size.width/(float)screen_frame.size.height; | |
133 | |
134 //set aspect | |
135 panscan_init(); | |
136 aspect_save_orig(width,height); | |
137 aspect_save_prescale(d_width,d_height); | |
138 aspect_save_screenres(screen_frame.size.width, screen_frame.size.height); | |
139 aspect((int *)&d_width,(int *)&d_height,A_NOZOOM); | |
140 | |
141 movie_aspect = (float)d_width/(float)d_height; | |
142 old_movie_aspect = movie_aspect; | |
15726 | 143 |
16385 | 144 vo_fs = flags & VOFLAG_FULLSCREEN; |
145 | |
146 //config OpenGL View | |
147 [mpGLView config]; | |
148 [mpGLView reshape]; | |
149 } | |
150 else | |
151 { | |
152 movie_aspect = (float)d_width/(float)d_height; | |
153 | |
154 shm_id = shmget(9849, image_width*image_height*image_bytes, IPC_CREAT | 0666); | |
155 if (shm_id == -1) | |
156 { | |
157 perror("vo_mplayer shmget: "); | |
158 return 1; | |
159 } | |
160 | |
161 image_data = shmat(shm_id, NULL, 0); | |
162 if (!image_data) | |
163 { | |
164 perror("vo_mplayer shmat: "); | |
165 return 1; | |
166 } | |
167 | |
168 //connnect to mplayerosx | |
169 mplayerosxProxy=[NSConnection rootProxyForConnectionWithRegisteredName:@"mplayerosx" host:nil]; | |
18057 | 170 [mplayerosxProxy startWithWidth: image_width withHeight: image_height withBytes: image_bytes withAspect:(int)(movie_aspect*100)]; |
16385 | 171 } |
15289 | 172 return 0; |
173 } | |
174 | |
175 static void check_events(void) | |
176 { | |
15611 | 177 [mpGLView check_events]; |
15289 | 178 } |
179 | |
180 static void draw_osd(void) | |
181 { | |
182 vo_draw_text(image_width, image_height, draw_alpha); | |
183 } | |
184 | |
185 static void flip_page(void) | |
186 { | |
16385 | 187 if(shared_buffer) |
188 [mplayerosxProxy render]; | |
189 else | |
190 [mpGLView render]; | |
15289 | 191 } |
192 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
193 static int draw_slice(uint8_t *src[], int stride[], int w,int h,int x,int y) |
15289 | 194 { |
15611 | 195 [mpGLView setCurrentTexture]; |
15289 | 196 return 0; |
197 } | |
198 | |
199 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
200 static int draw_frame(uint8_t *src[]) |
15289 | 201 { |
202 switch (image_format) | |
203 { | |
204 case IMGFMT_BGR32: | |
205 case IMGFMT_RGB32: | |
206 memcpy(image_data, src[0], image_width*image_height*image_bytes); | |
207 break; | |
208 | |
209 case IMGFMT_YUY2: | |
210 memcpy_pic(image_data, src[0], image_width * 2, image_height, image_width * 2, image_width * 2); | |
211 break; | |
212 } | |
16385 | 213 |
214 if(!shared_buffer) | |
215 [mpGLView setCurrentTexture]; | |
216 | |
15289 | 217 return 0; |
218 } | |
219 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
220 static int query_format(uint32_t format) |
15289 | 221 { |
222 image_format = format; | |
223 | |
224 switch(format) | |
225 { | |
226 case IMGFMT_YUY2: | |
227 pixelFormat = kYUVSPixelFormat; | |
228 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN; | |
229 | |
230 case IMGFMT_RGB32: | |
231 case IMGFMT_BGR32: | |
232 pixelFormat = k32ARGBPixelFormat; | |
233 return VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN; | |
234 } | |
235 return 0; | |
236 } | |
237 | |
238 static void uninit(void) | |
239 { | |
16385 | 240 if(shared_buffer) |
241 { | |
242 [mplayerosxProxy stop]; | |
243 | |
244 if (shmdt(image_data) == -1) | |
245 mp_msg(MSGT_VO, MSGL_FATAL, "uninit: shmdt failed\n"); | |
246 | |
247 if (shmctl(shm_id, IPC_RMID, &shm_desc) == -1) | |
248 mp_msg(MSGT_VO, MSGL_FATAL, "uninit: shmctl failed\n"); | |
249 } | |
250 | |
16145 | 251 SetSystemUIMode( kUIModeNormal, 0); |
18057 | 252 CGDisplayShowCursor(kCGDirectMainDisplay); |
16385 | 253 |
15289 | 254 [autoreleasepool release]; |
255 } | |
256 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
257 static int preinit(const char *arg) |
15289 | 258 { |
259 int parse_err = 0; | |
260 | |
15728 | 261 if(arg) |
262 { | |
263 char *parse_pos = (char *)&arg[0]; | |
264 while (parse_pos[0] && !parse_err) | |
265 { | |
266 if (strncmp (parse_pos, "device_id=", 10) == 0) | |
267 { | |
268 parse_pos = &parse_pos[10]; | |
269 screen_id = strtol(parse_pos, &parse_pos, 0); | |
270 screen_force = YES; | |
271 } | |
16385 | 272 if (strncmp (parse_pos, "shared_buffer", 13) == 0) |
273 { | |
274 parse_pos = &parse_pos[13]; | |
275 shared_buffer = YES; | |
276 } | |
15728 | 277 if (parse_pos[0] == ':') parse_pos = &parse_pos[1]; |
278 else if (parse_pos[0]) parse_err = 1; | |
279 } | |
280 } | |
281 | |
15737
0c3939433cef
set nsapp and setup cocoa with NSApplicationLoad
nplourde
parents:
15736
diff
changeset
|
282 NSApplicationLoad(); |
15289 | 283 autoreleasepool = [[NSAutoreleasePool alloc] init]; |
15737
0c3939433cef
set nsapp and setup cocoa with NSApplicationLoad
nplourde
parents:
15736
diff
changeset
|
284 NSApp = [NSApplication sharedApplication]; |
15726 | 285 |
16385 | 286 if(!shared_buffer) |
16144 | 287 { |
17358
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
288 #if !defined (MACOSX_FINDER_SUPPORT) || !defined (HAVE_SDL) |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
289 //this chunk of code is heavily based off SDL_macosx.m from SDL |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
290 //it uses an Apple private function to request foreground operation |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
291 void CPSEnableForegroundOperation(ProcessSerialNumber* psn); |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
292 ProcessSerialNumber myProc, frProc; |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
293 Boolean sameProc; |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
294 |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
295 if (GetFrontProcess(&frProc) == noErr) |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
296 { |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
297 if (GetCurrentProcess(&myProc) == noErr) |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
298 { |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
299 if (SameProcess(&frProc, &myProc, &sameProc) == noErr && !sameProc) |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
300 { |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
301 CPSEnableForegroundOperation(&myProc); |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
302 } |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
303 SetFrontProcess(&myProc); |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
304 } |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
305 } |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
306 #endif |
22ec2e9cb530
do not give focus to vo_macosx in shared buffer mode. Patch by Hector Chu<hectorchu@gmail.com>
nplourde
parents:
16385
diff
changeset
|
307 |
16385 | 308 if(!mpGLView) |
309 { | |
310 mpGLView = [[MPlayerOpenGLView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) pixelFormat:[MPlayerOpenGLView defaultPixelFormat]]; | |
311 [mpGLView autorelease]; | |
312 } | |
313 | |
314 [mpGLView display]; | |
315 [mpGLView preinit]; | |
16144 | 316 } |
317 | |
15289 | 318 return 0; |
319 } | |
320 | |
16171
fd51fd1ff231
Fix the return types of all (six) libvo API functions. Used to be uint32_t, but
ivo
parents:
16145
diff
changeset
|
321 static int control(uint32_t request, void *data, ...) |
15289 | 322 { |
323 switch (request) | |
324 { | |
325 case VOCTRL_PAUSE: return (int_pause=1); | |
326 case VOCTRL_RESUME: return (int_pause=0); | |
327 case VOCTRL_QUERY_FORMAT: return query_format(*((uint32_t*)data)); | |
15611 | 328 case VOCTRL_ONTOP: vo_ontop = (!(vo_ontop)); [mpGLView ontop]; return VO_TRUE; |
329 case VOCTRL_ROOTWIN: vo_rootwin = (!(vo_rootwin)); [mpGLView rootwin]; return VO_TRUE; | |
330 case VOCTRL_FULLSCREEN: vo_fs = (!(vo_fs)); [mpGLView fullscreen: YES]; return VO_TRUE; | |
15289 | 331 case VOCTRL_GET_PANSCAN: return VO_TRUE; |
15611 | 332 case VOCTRL_SET_PANSCAN: [mpGLView panscan]; return VO_TRUE; |
15289 | 333 } |
334 return VO_NOTIMPL; | |
335 } | |
336 | |
337 ////////////////////////////////////////////////////////////////////////// | |
338 // NSOpenGLView Subclass | |
339 ////////////////////////////////////////////////////////////////////////// | |
15611 | 340 @implementation MPlayerOpenGLView |
15726 | 341 - (id) preinit |
15289 | 342 { |
15726 | 343 //init menu |
344 [self initMenu]; | |
345 | |
346 //create window | |
15747
fbf14e1ab725
osx 10.3 dont like to have a window init with no size
nplourde
parents:
15737
diff
changeset
|
347 window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) |
15726 | 348 styleMask:NSTitledWindowMask|NSTexturedBackgroundWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask |
349 backing:NSBackingStoreBuffered defer:NO]; | |
350 | |
16144 | 351 [window autorelease]; |
15726 | 352 [window setDelegate:mpGLView]; |
353 [window setContentView:mpGLView]; | |
354 [window setInitialFirstResponder:mpGLView]; | |
355 [window setAcceptsMouseMovedEvents:YES]; | |
356 [window setTitle:@"MPlayer - The Movie Player"]; | |
357 | |
358 isFullscreen = 0; | |
15855 | 359 winSizeMult = 1; |
15726 | 360 } |
361 | |
362 - (id) config | |
363 { | |
364 uint32_t d_width; | |
365 uint32_t d_height; | |
366 | |
15610 | 367 long swapInterval = 1; |
15726 | 368 |
369 NSRect frame; | |
15289 | 370 CVReturn error = kCVReturnSuccess; |
371 | |
15728 | 372 //config window |
15726 | 373 aspect((int *)&d_width, (int *)&d_height,A_NOZOOM); |
374 frame = NSMakeRect(0, 0, d_width, d_height); | |
375 [window setContentSize: frame.size]; | |
15570 | 376 |
15289 | 377 //create OpenGL Context |
378 glContext = [[NSOpenGLContext alloc] initWithFormat:[NSOpenGLView defaultPixelFormat] shareContext:nil]; | |
15647 | 379 |
15289 | 380 [self setOpenGLContext:glContext]; |
15647 | 381 [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; |
15289 | 382 [glContext setView:self]; |
383 [glContext makeCurrentContext]; | |
384 | |
15647 | 385 error = CVPixelBufferCreateWithBytes( NULL, image_width, image_height, pixelFormat, image_data, image_width*image_bytes, NULL, NULL, NULL, ¤tFrameBuffer); |
15289 | 386 if(error != kCVReturnSuccess) |
387 mp_msg(MSGT_VO, MSGL_ERR,"Failed to create Pixel Buffer(%d)\n", error); | |
388 | |
389 error = CVOpenGLTextureCacheCreate(NULL, 0, [glContext CGLContextObj], [[self pixelFormat] CGLPixelFormatObj], 0, &textureCache); | |
390 if(error != kCVReturnSuccess) | |
391 mp_msg(MSGT_VO, MSGL_ERR,"Failed to create OpenGL texture Cache(%d)\n", error); | |
392 | |
393 error = CVOpenGLTextureCacheCreateTextureFromImage( NULL, textureCache, currentFrameBuffer, 0, &texture); | |
394 if(error != kCVReturnSuccess) | |
395 mp_msg(MSGT_VO, MSGL_ERR,"Failed to create OpenGL texture(%d)\n", error); | |
396 | |
15728 | 397 //show window |
398 [window center]; | |
399 [window makeKeyAndOrderFront:mpGLView]; | |
400 | |
15726 | 401 if(vo_rootwin) |
402 [mpGLView rootwin]; | |
403 | |
404 if(vo_fs) | |
405 [mpGLView fullscreen: NO]; | |
406 | |
407 if(vo_ontop) | |
408 [mpGLView ontop]; | |
15289 | 409 } |
410 | |
411 /* | |
15570 | 412 Init Menu |
413 */ | |
414 - (void)initMenu | |
415 { | |
416 NSMenu *menu; | |
417 NSMenuItem *menuItem; | |
418 | |
419 [NSApp setMainMenu:[[NSMenu alloc] init]]; | |
420 | |
421 //Create Movie Menu | |
422 menu = [[NSMenu alloc] initWithTitle:@"Movie"]; | |
423 menuItem = [[NSMenuItem alloc] initWithTitle:@"Half Size" action:@selector(menuAction:) keyEquivalent:@"0"]; [menu addItem:menuItem]; | |
424 kHalfScreenCmd = menuItem; | |
425 menuItem = [[NSMenuItem alloc] initWithTitle:@"Normal Size" action:@selector(menuAction:) keyEquivalent:@"1"]; [menu addItem:menuItem]; | |
426 kNormalScreenCmd = menuItem; | |
427 menuItem = [[NSMenuItem alloc] initWithTitle:@"Double Size" action:@selector(menuAction:) keyEquivalent:@"2"]; [menu addItem:menuItem]; | |
428 kDoubleScreenCmd = menuItem; | |
429 menuItem = [[NSMenuItem alloc] initWithTitle:@"Full Size" action:@selector(menuAction:) keyEquivalent:@"f"]; [menu addItem:menuItem]; | |
430 kFullScreenCmd = menuItem; | |
15909 | 431 menuItem = (NSMenuItem *)[NSMenuItem separatorItem]; [menu addItem:menuItem]; |
15570 | 432 |
433 NSMenu *aspectMenu; | |
434 aspectMenu = [[NSMenu alloc] initWithTitle:@"Aspect Ratio"]; | |
435 menuItem = [[NSMenuItem alloc] initWithTitle:@"Keep" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; | |
436 if(vo_keepaspect) [menuItem setState:NSOnState]; | |
437 kKeepAspectCmd = menuItem; | |
438 menuItem = [[NSMenuItem alloc] initWithTitle:@"Pan-Scan" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; | |
439 if(vo_panscan) [menuItem setState:NSOnState]; | |
440 kPanScanCmd = menuItem; | |
15909 | 441 menuItem = (NSMenuItem *)[NSMenuItem separatorItem]; [aspectMenu addItem:menuItem]; |
15570 | 442 menuItem = [[NSMenuItem alloc] initWithTitle:@"Original" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; |
443 kAspectOrgCmd = menuItem; | |
444 menuItem = [[NSMenuItem alloc] initWithTitle:@"4:3" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; | |
445 kAspectFullCmd = menuItem; | |
446 menuItem = [[NSMenuItem alloc] initWithTitle:@"16:9" action:@selector(menuAction:) keyEquivalent:@""]; [aspectMenu addItem:menuItem]; | |
447 kAspectWideCmd = menuItem; | |
448 menuItem = [[NSMenuItem alloc] initWithTitle:@"Aspect Ratio" action:nil keyEquivalent:@""]; | |
449 [menuItem setSubmenu:aspectMenu]; | |
450 [menu addItem:menuItem]; | |
451 [aspectMenu release]; | |
452 | |
453 //Add to menubar | |
454 menuItem = [[NSMenuItem alloc] initWithTitle:@"Movie" action:nil keyEquivalent:@""]; | |
455 [menuItem setSubmenu:menu]; | |
456 [[NSApp mainMenu] addItem:menuItem]; | |
457 | |
458 //Create Window Menu | |
459 menu = [[NSMenu alloc] initWithTitle:@"Window"]; | |
460 | |
461 menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menu addItem:menuItem]; | |
462 menuItem = [[NSMenuItem alloc] initWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""]; [menu addItem:menuItem]; | |
463 | |
464 //Add to menubar | |
465 menuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; | |
466 [menuItem setSubmenu:menu]; | |
467 [[NSApp mainMenu] addItem:menuItem]; | |
468 [NSApp setWindowsMenu:menu]; | |
469 | |
470 [menu release]; | |
471 [menuItem release]; | |
472 } | |
473 | |
474 /* | |
475 Menu Action | |
476 */ | |
477 - (void)menuAction:(id)sender | |
478 { | |
479 uint32_t d_width; | |
480 uint32_t d_height; | |
481 NSRect frame; | |
482 | |
483 aspect((int *)&d_width, (int *)&d_height,A_NOZOOM); | |
15731 | 484 |
485 if(sender == kQuitCmd) | |
486 { | |
487 mplayer_put_key(KEY_ESC); | |
488 } | |
15570 | 489 |
490 if(sender == kHalfScreenCmd) | |
491 { | |
492 if(isFullscreen) { | |
493 vo_fs = (!(vo_fs)); [self fullscreen:YES]; | |
494 } | |
495 | |
15855 | 496 winSizeMult = 0.5; |
497 frame.size.width = (d_width*winSizeMult); | |
498 frame.size.height = ((d_width/movie_aspect)*winSizeMult); | |
15570 | 499 [window setContentSize: frame.size]; |
500 [self reshape]; | |
501 } | |
502 if(sender == kNormalScreenCmd) | |
503 { | |
504 if(isFullscreen) { | |
505 vo_fs = (!(vo_fs)); [self fullscreen:YES]; | |
506 } | |
507 | |
15855 | 508 winSizeMult = 1; |
15570 | 509 frame.size.width = d_width; |
510 frame.size.height = d_width/movie_aspect; | |
511 [window setContentSize: frame.size]; | |
512 [self reshape]; | |
513 } | |
514 if(sender == kDoubleScreenCmd) | |
515 { | |
516 if(isFullscreen) { | |
517 vo_fs = (!(vo_fs)); [self fullscreen:YES]; | |
518 } | |
519 | |
15855 | 520 winSizeMult = 2; |
521 frame.size.width = d_width*winSizeMult; | |
522 frame.size.height = (d_width/movie_aspect)*winSizeMult; | |
15570 | 523 [window setContentSize: frame.size]; |
524 [self reshape]; | |
525 } | |
526 if(sender == kFullScreenCmd) | |
527 { | |
528 vo_fs = (!(vo_fs)); | |
529 [self fullscreen:YES]; | |
530 } | |
531 | |
532 if(sender == kKeepAspectCmd) | |
533 { | |
534 vo_keepaspect = (!(vo_keepaspect)); | |
535 if(vo_keepaspect) | |
536 [kKeepAspectCmd setState:NSOnState]; | |
537 else | |
538 [kKeepAspectCmd setState:NSOffState]; | |
15909 | 539 |
540 [self reshape]; | |
15570 | 541 } |
542 | |
543 if(sender == kPanScanCmd) | |
544 { | |
545 vo_panscan = (!(vo_panscan)); | |
546 if(vo_panscan) | |
547 [kPanScanCmd setState:NSOnState]; | |
548 else | |
549 [kPanScanCmd setState:NSOffState]; | |
15902
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
550 |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
551 [self panscan]; |
15570 | 552 } |
553 | |
554 if(sender == kAspectOrgCmd) | |
555 { | |
556 movie_aspect = old_movie_aspect; | |
15902
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
557 |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
558 if(isFullscreen) |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
559 { |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
560 [self reshape]; |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
561 } |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
562 else |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
563 { |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
564 frame.size.width = d_width*winSizeMult; |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
565 frame.size.height = (d_width/movie_aspect)*winSizeMult; |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
566 [window setContentSize: frame.size]; |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
567 [self reshape]; |
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
568 } |
15570 | 569 } |
570 | |
571 if(sender == kAspectFullCmd) | |
572 { | |
573 movie_aspect = 4.0f/3.0f; | |
15882 | 574 |
575 if(isFullscreen) | |
576 { | |
577 [self reshape]; | |
578 } | |
579 else | |
580 { | |
581 frame.size.width = d_width*winSizeMult; | |
582 frame.size.height = (d_width/movie_aspect)*winSizeMult; | |
583 [window setContentSize: frame.size]; | |
584 [self reshape]; | |
585 } | |
15570 | 586 } |
587 | |
588 if(sender == kAspectWideCmd) | |
589 { | |
590 movie_aspect = 16.0f/9.0f; | |
15882 | 591 |
592 if(isFullscreen) | |
593 { | |
594 [self reshape]; | |
595 } | |
596 else | |
597 { | |
598 frame.size.width = d_width*winSizeMult; | |
599 frame.size.height = (d_width/movie_aspect)*winSizeMult; | |
600 [window setContentSize: frame.size]; | |
601 [self reshape]; | |
602 } | |
15570 | 603 } |
604 } | |
605 | |
606 /* | |
15289 | 607 Setup OpenGL |
608 */ | |
609 - (void)prepareOpenGL | |
610 { | |
15339 | 611 glEnable(GL_BLEND); |
15289 | 612 glDisable(GL_DEPTH_TEST); |
613 glDepthMask(GL_FALSE); | |
614 glDisable(GL_CULL_FACE); | |
615 [self reshape]; | |
616 } | |
617 | |
618 /* | |
619 reshape OpenGL viewport | |
620 */ | |
621 - (void)reshape | |
622 { | |
623 uint32_t d_width; | |
624 uint32_t d_height; | |
625 float aspectX; | |
626 float aspectY; | |
627 int padding = 0; | |
628 | |
629 NSRect frame = [self frame]; | |
630 | |
631 glViewport(0, 0, frame.size.width, frame.size.height); | |
632 glMatrixMode(GL_PROJECTION); | |
633 glLoadIdentity(); | |
634 glOrtho(0, frame.size.width, frame.size.height, 0, -1.0, 1.0); | |
635 glMatrixMode(GL_MODELVIEW); | |
636 glLoadIdentity(); | |
637 | |
15729 | 638 //set texture frame |
15289 | 639 if(vo_keepaspect) |
640 { | |
15571 | 641 aspect( (int *)&d_width, (int *)&d_height, A_NOZOOM); |
15289 | 642 d_height = ((float)d_width/movie_aspect); |
643 | |
644 aspectX = (float)((float)frame.size.width/(float)d_width); | |
645 aspectY = (float)((float)(frame.size.height)/(float)d_height); | |
646 | |
647 if((d_height*aspectX)>(frame.size.height)) | |
648 { | |
649 padding = (frame.size.width - d_width*aspectY)/2; | |
15729 | 650 textureFrame = NSMakeRect(padding, 0, d_width*aspectY+padding, d_height*aspectY); |
15289 | 651 } |
652 else | |
653 { | |
654 padding = ((frame.size.height) - d_height*aspectX)/2; | |
15729 | 655 textureFrame = NSMakeRect(0, padding, d_width*aspectX, d_height*aspectX+padding); |
15289 | 656 } |
657 } | |
658 else | |
659 { | |
15729 | 660 textureFrame = frame; |
15289 | 661 } |
662 } | |
663 | |
664 /* | |
665 Render frame | |
666 */ | |
667 - (void) render | |
668 { | |
669 glClear(GL_COLOR_BUFFER_BIT); | |
670 | |
671 glEnable(CVOpenGLTextureGetTarget(texture)); | |
672 glBindTexture(CVOpenGLTextureGetTarget(texture), CVOpenGLTextureGetName(texture)); | |
673 | |
674 glColor3f(1,1,1); | |
675 glBegin(GL_QUADS); | |
15729 | 676 glTexCoord2f(upperLeft[0], upperLeft[1]); glVertex2i( textureFrame.origin.x-(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); |
677 glTexCoord2f(lowerLeft[0], lowerLeft[1]); glVertex2i( textureFrame.origin.x-(vo_panscan_x >> 1), textureFrame.size.height+(vo_panscan_y >> 1)); | |
678 glTexCoord2f(lowerRight[0], lowerRight[1]); glVertex2i( textureFrame.size.width+(vo_panscan_x >> 1), textureFrame.size.height+(vo_panscan_y >> 1)); | |
679 glTexCoord2f(upperRight[0], upperRight[1]); glVertex2i( textureFrame.size.width+(vo_panscan_x >> 1), textureFrame.origin.y-(vo_panscan_y >> 1)); | |
15289 | 680 glEnd(); |
15339 | 681 glDisable(CVOpenGLTextureGetTarget(texture)); |
682 | |
683 //render resize box | |
684 if(!isFullscreen) | |
685 { | |
686 NSRect frame = [self frame]; | |
687 | |
688 glBegin(GL_LINES); | |
689 glColor4f(0.2, 0.2, 0.2, 0.5); | |
690 glVertex2i(frame.size.width-1, frame.size.height-1); glVertex2i(frame.size.width-1, frame.size.height-1); | |
691 glVertex2i(frame.size.width-1, frame.size.height-5); glVertex2i(frame.size.width-5, frame.size.height-1); | |
692 glVertex2i(frame.size.width-1, frame.size.height-9); glVertex2i(frame.size.width-9, frame.size.height-1); | |
693 | |
694 glColor4f(0.4, 0.4, 0.4, 0.5); | |
695 glVertex2i(frame.size.width-1, frame.size.height-2); glVertex2i(frame.size.width-2, frame.size.height-1); | |
696 glVertex2i(frame.size.width-1, frame.size.height-6); glVertex2i(frame.size.width-6, frame.size.height-1); | |
697 glVertex2i(frame.size.width-1, frame.size.height-10); glVertex2i(frame.size.width-10, frame.size.height-1); | |
698 | |
699 glColor4f(0.6, 0.6, 0.6, 0.5); | |
700 glVertex2i(frame.size.width-1, frame.size.height-3); glVertex2i(frame.size.width-3, frame.size.height-1); | |
701 glVertex2i(frame.size.width-1, frame.size.height-7); glVertex2i(frame.size.width-7, frame.size.height-1); | |
702 glVertex2i(frame.size.width-1, frame.size.height-11); glVertex2i(frame.size.width-11, frame.size.height-1); | |
703 glEnd(); | |
704 } | |
15289 | 705 |
706 glFlush(); | |
707 | |
708 //auto hide mouse cursor and futur on-screen control? | |
15327 | 709 if(isFullscreen && !mouseHide && !isRootwin) |
15289 | 710 { |
18057 | 711 int curTime = TickCount()/60; |
712 static int lastTime = 0; | |
15289 | 713 |
714 if( ((curTime - lastTime) >= 5) || (lastTime == 0) ) | |
715 { | |
18057 | 716 CGDisplayHideCursor(kCGDirectMainDisplay); |
15289 | 717 mouseHide = YES; |
718 lastTime = curTime; | |
719 } | |
720 } | |
17546 | 721 |
17725 | 722 //update activity every 30 seconds to prevent |
17546 | 723 //screensaver from starting up. |
18057 | 724 int curTime = TickCount()/60; |
725 static int lastTime = 0; | |
726 | |
727 if( ((curTime - lastTime) >= 30) || (lastTime == 0) ) | |
17546 | 728 { |
729 UpdateSystemActivity(UsrActivity); | |
730 lastTime = curTime; | |
731 } | |
15289 | 732 } |
733 | |
734 /* | |
735 Create OpenGL texture from current frame & set texco | |
736 */ | |
737 - (void) setCurrentTexture | |
738 { | |
739 CVReturn error = kCVReturnSuccess; | |
740 | |
741 error = CVOpenGLTextureCacheCreateTextureFromImage (NULL, textureCache, currentFrameBuffer, 0, &texture); | |
742 if(error != kCVReturnSuccess) | |
743 mp_msg(MSGT_VO, MSGL_ERR,"Failed to create OpenGL texture(%d)\n", error); | |
744 | |
745 CVOpenGLTextureGetCleanTexCoords(texture, lowerLeft, lowerRight, upperRight, upperLeft); | |
746 } | |
747 | |
748 /* | |
749 redraw win rect | |
750 */ | |
751 - (void) drawRect: (NSRect *) bounds | |
752 { | |
753 [self render]; | |
754 } | |
755 | |
756 /* | |
757 Toggle Fullscreen | |
758 */ | |
759 - (void) fullscreen: (BOOL) animate | |
760 { | |
761 static NSRect old_frame; | |
762 static NSRect old_view_frame; | |
15728 | 763 |
764 if(screen_force) | |
765 screen_frame = [screen_handle frame]; | |
766 else | |
767 screen_frame = [[window screen] frame]; | |
15289 | 768 |
15573 | 769 panscan_calc(); |
770 | |
15289 | 771 //go fullscreen |
772 if(vo_fs) | |
773 { | |
15327 | 774 if(!isRootwin) |
775 { | |
15882 | 776 SetSystemUIMode( kUIModeAllHidden, kUIOptionAutoShowMenuBar); |
18057 | 777 CGDisplayHideCursor(kCGDirectMainDisplay); |
15327 | 778 mouseHide = YES; |
779 } | |
15289 | 780 |
781 old_frame = [window frame]; //save main window size & position | |
15728 | 782 [window setFrame:screen_frame display:YES animate:animate]; //zoom-in window with nice useless sfx |
15289 | 783 old_view_frame = [self bounds]; |
784 | |
785 //fix origin for multi screen setup | |
15728 | 786 screen_frame.origin.x = 0; |
787 screen_frame.origin.y = 0; | |
788 [self setFrame:screen_frame]; | |
15289 | 789 [self setNeedsDisplay:YES]; |
790 [window setHasShadow:NO]; | |
791 isFullscreen = 1; | |
792 } | |
793 else | |
15882 | 794 { |
15902
16534910f0fb
fix various window resizing bug with menu option
nplourde
parents:
15882
diff
changeset
|
795 SetSystemUIMode( kUIModeNormal, 0); |
15882 | 796 |
15289 | 797 isFullscreen = 0; |
18057 | 798 CGDisplayShowCursor(kCGDirectMainDisplay); |
15289 | 799 mouseHide = NO; |
800 | |
801 //revert window to previous setting | |
802 [self setFrame:old_view_frame]; | |
803 [self setNeedsDisplay:YES]; | |
16081
72c352edce8f
restore window shadow when quitting fullscreen mode
nplourde
parents:
15909
diff
changeset
|
804 [window setHasShadow:YES]; |
15289 | 805 [window setFrame:old_frame display:YES animate:animate];//zoom-out window with nice useless sfx |
806 } | |
807 } | |
808 | |
809 /* | |
810 Toggle ontop | |
811 */ | |
812 - (void) ontop | |
813 { | |
15320 | 814 if(vo_ontop) |
815 { | |
816 [window setLevel:NSScreenSaverWindowLevel]; | |
817 isOntop = YES; | |
818 } | |
819 else | |
820 { | |
821 [window setLevel:NSNormalWindowLevel]; | |
822 isOntop = NO; | |
823 } | |
15289 | 824 } |
825 | |
826 /* | |
827 Toggle panscan | |
828 */ | |
829 - (void) panscan | |
830 { | |
15331 | 831 panscan_calc(); |
15289 | 832 } |
833 | |
834 /* | |
15327 | 835 Toggle rootwin |
836 */ | |
837 - (void) rootwin | |
838 { | |
839 if(vo_rootwin) | |
840 { | |
841 [window setLevel:CGWindowLevelForKey(kCGDesktopWindowLevelKey)]; | |
842 [window orderBack:self]; | |
843 isRootwin = YES; | |
844 } | |
845 else | |
846 { | |
847 [window setLevel:NSNormalWindowLevel]; | |
848 isRootwin = NO; | |
849 } | |
850 } | |
851 | |
852 /* | |
15289 | 853 Check event for new event |
854 */ | |
855 - (void) check_events | |
856 { | |
857 event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.0001] inMode:NSEventTrackingRunLoopMode dequeue:YES]; | |
858 [NSApp sendEvent:event]; | |
859 } | |
860 | |
861 /* | |
15731 | 862 From NSView, respond to key equivalents. |
863 */ | |
864 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent | |
865 { | |
866 switch([theEvent keyCode]) | |
867 { | |
868 case 0x21: [window setAlphaValue: winAlpha-=0.05]; return YES; | |
869 case 0x1e: [window setAlphaValue: winAlpha+=0.05]; return YES; | |
870 } | |
871 return NO; | |
872 } | |
873 | |
874 /* | |
15289 | 875 Process key event |
876 */ | |
877 - (void) keyDown: (NSEvent *) theEvent | |
878 { | |
879 unsigned int key; | |
880 | |
881 switch([theEvent keyCode]) | |
882 { | |
883 case 0x34: | |
884 case 0x24: key = KEY_ENTER; break; | |
885 case 0x35: key = KEY_ESC; break; | |
886 case 0x33: key = KEY_BACKSPACE; break; | |
887 case 0x3A: key = KEY_BACKSPACE; break; | |
888 case 0x3B: key = KEY_BACKSPACE; break; | |
889 case 0x38: key = KEY_BACKSPACE; break; | |
890 case 0x7A: key = KEY_F+1; break; | |
891 case 0x78: key = KEY_F+2; break; | |
892 case 0x63: key = KEY_F+3; break; | |
893 case 0x76: key = KEY_F+4; break; | |
894 case 0x60: key = KEY_F+5; break; | |
895 case 0x61: key = KEY_F+6; break; | |
896 case 0x62: key = KEY_F+7; break; | |
897 case 0x64: key = KEY_F+8; break; | |
898 case 0x65: key = KEY_F+9; break; | |
899 case 0x6D: key = KEY_F+10; break; | |
900 case 0x67: key = KEY_F+11; break; | |
901 case 0x6F: key = KEY_F+12; break; | |
902 case 0x72: key = KEY_INSERT; break; | |
903 case 0x75: key = KEY_DELETE; break; | |
904 case 0x73: key = KEY_HOME; break; | |
905 case 0x77: key = KEY_END; break; | |
906 case 0x45: key = '+'; break; | |
907 case 0x4E: key = '-'; break; | |
908 case 0x30: key = KEY_TAB; break; | |
909 case 0x74: key = KEY_PAGE_UP; break; | |
910 case 0x79: key = KEY_PAGE_DOWN; break; | |
911 case 0x7B: key = KEY_LEFT; break; | |
912 case 0x7C: key = KEY_RIGHT; break; | |
913 case 0x7D: key = KEY_DOWN; break; | |
914 case 0x7E: key = KEY_UP; break; | |
915 case 0x43: key = '*'; break; | |
916 case 0x4B: key = '/'; break; | |
917 case 0x4C: key = KEY_BACKSPACE; break; | |
918 case 0x41: key = KEY_KPDEC; break; | |
919 case 0x52: key = KEY_KP0; break; | |
920 case 0x53: key = KEY_KP1; break; | |
921 case 0x54: key = KEY_KP2; break; | |
922 case 0x55: key = KEY_KP3; break; | |
923 case 0x56: key = KEY_KP4; break; | |
924 case 0x57: key = KEY_KP5; break; | |
925 case 0x58: key = KEY_KP6; break; | |
926 case 0x59: key = KEY_KP7; break; | |
927 case 0x5B: key = KEY_KP8; break; | |
928 case 0x5C: key = KEY_KP9; break; | |
929 default: key = *[[theEvent characters] UTF8String]; break; | |
930 } | |
931 mplayer_put_key(key); | |
932 } | |
933 | |
934 /* | |
935 Process mouse button event | |
936 */ | |
937 - (void) mouseMoved: (NSEvent *) theEvent | |
938 { | |
15327 | 939 if(isFullscreen && !isRootwin) |
15289 | 940 { |
18057 | 941 CGDisplayShowCursor(kCGDirectMainDisplay); |
15289 | 942 mouseHide = NO; |
943 } | |
944 } | |
945 | |
946 - (void) mouseDown: (NSEvent *) theEvent | |
947 { | |
948 [self mouseEvent: theEvent]; | |
949 } | |
950 | |
951 - (void) rightMouseDown: (NSEvent *) theEvent | |
952 { | |
953 [self mouseEvent: theEvent]; | |
954 } | |
955 | |
956 - (void) otherMouseDown: (NSEvent *) theEvent | |
957 { | |
958 [self mouseEvent: theEvent]; | |
959 } | |
960 | |
961 - (void) scrollWheel: (NSEvent *) theEvent | |
962 { | |
963 if([theEvent deltaY] > 0) | |
964 mplayer_put_key(MOUSE_BTN3); | |
965 else | |
966 mplayer_put_key(MOUSE_BTN4); | |
967 } | |
968 | |
969 - (void) mouseEvent: (NSEvent *) theEvent | |
970 { | |
971 switch( [theEvent buttonNumber] ) | |
972 { | |
973 case 0: mplayer_put_key(MOUSE_BTN0);break; | |
974 case 1: mplayer_put_key(MOUSE_BTN1);break; | |
975 case 2: mplayer_put_key(MOUSE_BTN2);break; | |
976 } | |
977 } | |
978 | |
979 /* | |
980 NSResponder | |
981 */ | |
982 - (BOOL) acceptsFirstResponder | |
983 { | |
984 return YES; | |
985 } | |
986 | |
987 - (BOOL) becomeFirstResponder | |
988 { | |
989 return YES; | |
990 } | |
991 | |
992 - (BOOL) resignFirstResponder | |
993 { | |
994 return YES; | |
995 } | |
15325 | 996 |
997 - (void)windowWillClose:(NSNotification *)aNotification | |
998 { | |
999 mplayer_put_key(KEY_ESC); | |
1000 } | |
1001 @end |