]> git.sesse.net Git - vlc/blob - modules/gui/minimal_macosx/intf.m
flac decoder: supports avformat extradata
[vlc] / modules / gui / minimal_macosx / intf.m
1 /*****************************************************************************
2  * intf.m: MacOS X interface module
3  *****************************************************************************
4  * Copyright (C) 2002-2012 VLC authors and VideoLAN
5  * $Id$
6  *
7  * Authors: Pierre d'Herbemont <pdherbemont # videolan.org>
8  *          Felix Paul Kühne <fkuehne at videolan dot org>
9  *
10  * This program is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation; either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this program; if not, write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #import <stdlib.h>                                      /* malloc(), free() */
29 #import <sys/param.h>                                    /* for MAXPATHLEN */
30 #import <string.h>
31 #ifdef HAVE_CONFIG_H
32 # import "config.h"
33 #endif
34
35 #import <vlc_playlist.h>
36 #import <vlc_vout_window.h>
37
38 #import "intf.h"
39 #import "VLCMinimalVoutWindow.h"
40
41 /*****************************************************************************
42  * Local prototypes.
43  *****************************************************************************/
44 static void Run (intf_thread_t *p_intf);
45
46 /*****************************************************************************
47  * OpenIntf: initialize interface
48  *****************************************************************************/
49 int OpenIntf (vlc_object_t *p_this)
50 {
51     intf_thread_t *p_intf = (intf_thread_t*) p_this;
52
53     p_intf->p_sys = malloc(sizeof(intf_sys_t));
54     if (p_intf->p_sys == NULL)
55         return VLC_ENOMEM;
56
57     memset(p_intf->p_sys, 0, sizeof(*p_intf->p_sys));
58
59     Run(p_intf);
60
61     return VLC_SUCCESS;
62 }
63
64 /*****************************************************************************
65  * CloseIntf: destroy interface
66  *****************************************************************************/
67 void CloseIntf (vlc_object_t *p_this)
68 {
69     intf_thread_t *p_intf = (intf_thread_t*) p_this;
70
71     free(p_intf->p_sys);
72 }
73
74 /* Dock Connection */
75 typedef struct CPSProcessSerNum
76 {
77         UInt32                lo;
78         UInt32                hi;
79 } CPSProcessSerNum;
80
81 extern OSErr    CPSGetCurrentProcess(CPSProcessSerNum *psn);
82 extern OSErr    CPSEnableForegroundOperation(CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
83 extern OSErr    CPSSetFrontProcess(CPSProcessSerNum *psn);
84
85 /*****************************************************************************
86  * KillerThread: Thread that kill the application
87  *****************************************************************************/
88 static void * KillerThread(void *user_data)
89 {
90     NSAutoreleasePool * o_pool = [[NSAutoreleasePool alloc] init];
91
92     intf_thread_t *p_intf = user_data;
93
94     vlc_mutex_init(&p_intf->p_sys->lock);
95     vlc_cond_init(&p_intf->p_sys->wait);
96
97     vlc_mutex_lock (&p_intf->p_sys->lock);
98     while(vlc_object_alive(p_intf))
99         vlc_cond_wait(&p_intf->p_sys->wait, &p_intf->p_sys->lock);
100     vlc_mutex_unlock(&p_intf->p_sys->lock);
101
102     vlc_mutex_destroy(&p_intf->p_sys->lock);
103     vlc_cond_destroy(&p_intf->p_sys->wait);
104
105     /* We are dead, terminate */
106     [NSApp terminate: nil];
107     [o_pool release];
108     return NULL;
109 }
110
111 /*****************************************************************************
112  * Run: main loop
113  *****************************************************************************/
114 static void Run(intf_thread_t *p_intf)
115 {
116     sigset_t set;
117
118     /* Make sure the "force quit" menu item does quit instantly.
119      * VLC overrides SIGTERM which is sent by the "force quit"
120      * menu item to make sure deamon mode quits gracefully, so
121      * we un-override SIGTERM here. */
122     sigemptyset(&set);
123     sigaddset(&set, SIGTERM);
124     pthread_sigmask(SIG_UNBLOCK, &set, NULL);
125
126     /* Setup a thread that will monitor the module killing */
127     pthread_t killer_thread;
128     pthread_create(&killer_thread, NULL, KillerThread, p_intf);
129
130     CPSProcessSerNum PSN;
131     NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
132     [NSApplication sharedApplication];
133     if (!CPSGetCurrentProcess(&PSN))
134         if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
135             if (!CPSSetFrontProcess(&PSN))
136                 [NSApplication sharedApplication];
137     [NSApp run];
138
139     pthread_join(killer_thread, NULL);
140
141     [pool release];
142 }
143
144 /*****************************************************************************
145  * Vout window management
146  *****************************************************************************/
147 static int WindowControl(vout_window_t *, int i_query, va_list);
148
149 int WindowOpen(vout_window_t *p_wnd, const vout_window_cfg_t *cfg)
150 {
151     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
152
153     NSRect proposedVideoViewPosition = NSMakeRect(cfg->x, cfg->y, cfg->width, cfg->height);
154
155     VLCMinimalVoutWindow *o_window = [[VLCMinimalVoutWindow alloc] initWithContentRect:proposedVideoViewPosition];
156     [o_window makeKeyAndOrderFront:nil];
157
158     if (!o_window) {
159         msg_Err(p_wnd, "window creation failed");
160         [o_pool release];
161         return VLC_EGENERIC;
162     }
163
164     msg_Dbg(p_wnd, "returning video window with proposed position x=%i, y=%i, width=%i, height=%i", cfg->x, cfg->y, cfg->width, cfg->height);
165     p_wnd->handle.nsobject = [o_window contentView];
166
167     // TODO: find a cleaner way for "start in fullscreen"
168     if (var_GetBool(pl_Get(p_wnd), "fullscreen"))
169         [o_window performSelectorOnMainThread:@selector(enterFullscreen) withObject:nil waitUntilDone:NO];
170
171     p_wnd->control = WindowControl;
172
173     [o_pool release];
174     return VLC_SUCCESS;
175 }
176
177 static int WindowControl(vout_window_t *p_wnd, int i_query, va_list args)
178 {
179     NSWindow * o_window = [(id)p_wnd->handle.nsobject window];
180     if (!o_window) {
181         msg_Err(p_wnd, "failed to recover cocoa window");
182         return VLC_EGENERIC;
183     }
184
185     switch (i_query) {
186         case VOUT_WINDOW_SET_STATE:
187         {
188             unsigned i_state = va_arg(args, unsigned);
189
190             [o_window setLevel: i_state];
191
192             return VLC_SUCCESS;
193         }
194         case VOUT_WINDOW_SET_SIZE:
195         {
196             NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
197
198             NSRect theFrame = [o_window frame];
199             unsigned int i_width  = va_arg(args, unsigned int);
200             unsigned int i_height = va_arg(args, unsigned int);
201             theFrame.size.width = i_width;
202             theFrame.size.height = i_height;
203             [o_window setFrame: theFrame display: YES animate: YES];
204
205             [o_pool release];
206             return VLC_SUCCESS;
207         }
208         case VOUT_WINDOW_SET_FULLSCREEN:
209         {
210             NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
211             int i_full = va_arg(args, int);
212
213             if (i_full)
214                 [o_window performSelectorOnMainThread:@selector(enterFullscreen) withObject:nil waitUntilDone:NO];
215             else
216                 [o_window performSelectorOnMainThread:@selector(leaveFullscreen) withObject:nil waitUntilDone:NO];
217
218             [o_pool release];
219             return VLC_SUCCESS;
220         }
221         default:
222             msg_Warn(p_wnd, "unsupported control query");
223             return VLC_EGENERIC;
224     }
225 }
226
227 void WindowClose(vout_window_t *p_wnd)
228 {
229     NSAutoreleasePool *o_pool = [[NSAutoreleasePool alloc] init];
230
231     NSWindow * o_window = [(id)p_wnd->handle.nsobject window];
232     if (o_window)
233         [o_window release];
234
235     [o_pool release];
236 }
237