3 * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
21 #include <Cocoa/Cocoa.h>
23 #include <gst/video/videooverlay.h>
25 /* ============================================================= */
29 /* ============================================================= */
31 @interface MainWindow: NSWindow <NSApplicationDelegate> {
33 GstElement *m_pipeline;
36 - (id) initWithContentRect:(NSRect) contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline;
38 - (GstElement*) pipeline;
39 - (gboolean) isClosed;
42 @implementation MainWindow
44 - (id) initWithContentRect:(NSRect)contentRect Loop:(GMainLoop*)loop Pipeline:(GstElement*)pipeline
47 m_pipeline = pipeline;
50 self = [super initWithContentRect: contentRect
51 styleMask: (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask)
52 backing: NSBackingStoreBuffered defer: NO screen: nil];
54 [self setReleasedWhenClosed:NO];
55 [[NSApplication sharedApplication] setDelegate:self];
57 [self setTitle:@"gst-plugins-gl implements videooverlay interface"];
66 - (GstElement*) pipeline {
70 - (gboolean) isClosed {
74 - (void) customClose {
78 - (BOOL) windowShouldClose:(id)sender {
79 gst_element_send_event (m_pipeline, gst_event_new_eos ());
83 - (void) applicationDidFinishLaunching: (NSNotification *) not {
84 [self makeMainWindow];
86 [self orderFront:self];
89 - (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app {
96 /* ============================================================= */
98 /* gstreamer callbacks */
100 /* ============================================================= */
103 static GstBusSyncReply create_window (GstBus* bus, GstMessage* message, MainWindow* window)
105 // ignore anything but 'prepare-window-handle' element messages
106 if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT)
109 if (!gst_is_video_overlay_prepare_window_handle_message (message))
112 g_print ("setting window handle %lud\n", (gulong) window);
114 gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), (guintptr) [window contentView]);
116 gst_message_unref (message);
122 static void end_stream_cb(GstBus* bus, GstMessage* message, MainWindow* window)
124 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
126 g_print ("end of stream\n");
128 gst_element_set_state ([window pipeline], GST_STATE_NULL);
129 gst_object_unref ([window pipeline]);
130 g_main_loop_quit ([window loop]);
132 [window performSelectorOnMainThread:@selector(customClose) withObject:nil waitUntilDone:YES];
137 static gpointer thread_func (MainWindow* window)
139 g_main_loop_run ([window loop]);
145 /* ============================================================= */
149 /* ============================================================= */
151 int main(int argc, char **argv)
156 GMainLoop *loop = NULL;
157 GstElement *pipeline = NULL;
159 GstElement *videosrc = NULL;
160 GstElement *videosink = NULL;
164 GThread *loop_thread=NULL;
165 NSAutoreleasePool *pool=nil;
167 MainWindow *window=nil;
169 g_print("app created\n");
171 gst_init (&argc, &argv);
173 loop = g_main_loop_new (NULL, FALSE);
174 pipeline = gst_pipeline_new ("pipeline");
176 videosrc = gst_element_factory_make ("videotestsrc", "videotestsrc");
177 videosink = gst_element_factory_make ("glimagesink", "glimagesink");
179 g_object_set(G_OBJECT(videosrc), "num-buffers", 500, NULL);
181 gst_bin_add_many (GST_BIN (pipeline), videosrc, videosink, NULL);
183 caps = gst_caps_new_simple("video/x-raw",
184 "width", G_TYPE_INT, width,
185 "height", G_TYPE_INT, height,
186 "framerate", GST_TYPE_FRACTION, 25, 1,
187 "format", G_TYPE_STRING, "I420",
190 ok = gst_element_link_filtered(videosrc, videosink, caps);
191 gst_caps_unref(caps);
193 g_warning("could not link videosrc to videosink\n");
195 pool = [[NSAutoreleasePool alloc] init];
196 [NSApplication sharedApplication];
198 rect.origin.x = 0; rect.origin.y = 0;
199 rect.size.width = width; rect.size.height = height;
201 window = [[MainWindow alloc] initWithContentRect:rect Loop:loop Pipeline:pipeline];
203 bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
204 gst_bus_add_signal_watch (bus);
205 g_signal_connect(bus, "message::error", G_CALLBACK(end_stream_cb), window);
206 g_signal_connect(bus, "message::warning", G_CALLBACK(end_stream_cb), window);
207 g_signal_connect(bus, "message::eos", G_CALLBACK(end_stream_cb), window);
208 gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, window, NULL);
209 gst_object_unref (bus);
211 loop_thread = g_thread_new (NULL,
212 (GThreadFunc) thread_func, window);
214 gst_element_set_state (pipeline, GST_STATE_PLAYING);
216 [window orderFront:window];
218 while (![window isClosed]) {
219 NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
220 untilDate:[NSDate dateWithTimeIntervalSinceNow:1]
221 inMode:NSDefaultRunLoopMode dequeue:YES];
223 [NSApp sendEvent:event];
226 g_thread_join (loop_thread);