WebKitExamplePlugins/NetscapeCoreAnimationMoviePlugin/main.m
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2      File: MovieControllerLayer.m
       
     3  
       
     4  Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
       
     5  Inc. ("Apple") in consideration of your agreement to the following
       
     6  terms, and your use, installation, modification or redistribution of
       
     7  this Apple software constitutes acceptance of these terms.  If you do
       
     8  not agree with these terms, please do not use, install, modify or
       
     9  redistribute this Apple software.
       
    10  
       
    11  In consideration of your agreement to abide by the following terms, and
       
    12  subject to these terms, Apple grants you a personal, non-exclusive
       
    13  license, under Apple's copyrights in this original Apple software (the
       
    14  "Apple Software"), to use, reproduce, modify and redistribute the Apple
       
    15  Software, with or without modifications, in source and/or binary forms;
       
    16  provided that if you redistribute the Apple Software in its entirety and
       
    17  without modifications, you must retain this notice and the following
       
    18  text and disclaimers in all such redistributions of the Apple Software.
       
    19  Neither the name, trademarks, service marks or logos of Apple Inc. may
       
    20  be used to endorse or promote products derived from the Apple Software
       
    21  without specific prior written permission from Apple.  Except as
       
    22  expressly stated in this notice, no other rights or licenses, express or
       
    23  implied, are granted by Apple herein, including but not limited to any
       
    24  patent rights that may be infringed by your derivative works or by other
       
    25  works in which the Apple Software may be incorporated.
       
    26  
       
    27  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
       
    28  MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
       
    29  THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
       
    30  FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
       
    31  OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
       
    32  
       
    33  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
       
    34  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       
    35  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       
    36  INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
       
    37  MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
       
    38  AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
       
    39  STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
       
    40  POSSIBILITY OF SUCH DAMAGE.
       
    41  
       
    42  Copyright (C) 2009 Apple Inc. All Rights Reserved.
       
    43  
       
    44  */
       
    45 
       
    46 #import <WebKit/npapi.h>
       
    47 #import <WebKit/npfunctions.h>
       
    48 #import <WebKit/npruntime.h>
       
    49 
       
    50 #import <QuartzCore/QuartzCore.h>
       
    51 #import <QTKit/QTKit.h>
       
    52 
       
    53 #import "MovieControllerLayer.h"
       
    54 
       
    55 // Browser function table
       
    56 static NPNetscapeFuncs* browser;
       
    57 
       
    58 // Structure for per-instance storage
       
    59 typedef struct PluginObject
       
    60 {
       
    61     NPP npp;
       
    62     
       
    63     NPWindow window;
       
    64     
       
    65     CALayer *rootLayer;
       
    66     MovieControllerLayer *controllerLayer;
       
    67     QTMovieLayer *movieLayer;
       
    68     
       
    69     CALayer *mouseDownLayer;
       
    70     
       
    71     NSURL *movieURL;
       
    72     QTMovie *movie;
       
    73 } PluginObject;
       
    74 
       
    75 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved);
       
    76 NPError NPP_Destroy(NPP instance, NPSavedData** save);
       
    77 NPError NPP_SetWindow(NPP instance, NPWindow* window);
       
    78 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype);
       
    79 NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason);
       
    80 int32_t NPP_WriteReady(NPP instance, NPStream* stream);
       
    81 int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer);
       
    82 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
       
    83 void NPP_Print(NPP instance, NPPrint* platformPrint);
       
    84 int16_t NPP_HandleEvent(NPP instance, void* event);
       
    85 void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, void* notifyData);
       
    86 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value);
       
    87 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value);
       
    88 
       
    89 #pragma export on
       
    90 // Mach-o entry points
       
    91 NPError NP_Initialize(NPNetscapeFuncs *browserFuncs);
       
    92 NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
       
    93 void NP_Shutdown(void);
       
    94 #pragma export off
       
    95 
       
    96 NPError NP_Initialize(NPNetscapeFuncs* browserFuncs)
       
    97 {
       
    98     browser = browserFuncs;
       
    99     return NPERR_NO_ERROR;
       
   100 }
       
   101 
       
   102 NPError NP_GetEntryPoints(NPPluginFuncs* pluginFuncs)
       
   103 {
       
   104     pluginFuncs->version = 11;
       
   105     pluginFuncs->size = sizeof(pluginFuncs);
       
   106     pluginFuncs->newp = NPP_New;
       
   107     pluginFuncs->destroy = NPP_Destroy;
       
   108     pluginFuncs->setwindow = NPP_SetWindow;
       
   109     pluginFuncs->newstream = NPP_NewStream;
       
   110     pluginFuncs->destroystream = NPP_DestroyStream;
       
   111     pluginFuncs->asfile = NPP_StreamAsFile;
       
   112     pluginFuncs->writeready = NPP_WriteReady;
       
   113     pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write;
       
   114     pluginFuncs->print = NPP_Print;
       
   115     pluginFuncs->event = NPP_HandleEvent;
       
   116     pluginFuncs->urlnotify = NPP_URLNotify;
       
   117     pluginFuncs->getvalue = NPP_GetValue;
       
   118     pluginFuncs->setvalue = NPP_SetValue;
       
   119     
       
   120     return NPERR_NO_ERROR;
       
   121 }
       
   122 
       
   123 void NP_Shutdown(void)
       
   124 {
       
   125 
       
   126 }
       
   127 
       
   128 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* saved)
       
   129 {
       
   130     // Create per-instance storage
       
   131     PluginObject *obj = (PluginObject *)malloc(sizeof(PluginObject));
       
   132     bzero(obj, sizeof(PluginObject));
       
   133     
       
   134     obj->npp = instance;
       
   135     instance->pdata = obj;
       
   136     
       
   137     // Ask the browser if it supports the Core Animation drawing model
       
   138     NPBool supportsCoreAnimation;
       
   139     if (browser->getvalue(instance, NPNVsupportsCoreAnimationBool, &supportsCoreAnimation) != NPERR_NO_ERROR)
       
   140         supportsCoreAnimation = FALSE;
       
   141     
       
   142     if (!supportsCoreAnimation)
       
   143         return NPERR_INCOMPATIBLE_VERSION_ERROR;
       
   144     
       
   145     // If the browser supports the Core Animation drawing model, enable it.
       
   146     browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreAnimation);
       
   147 
       
   148     // If the browser supports the Cocoa event model, enable it.
       
   149     NPBool supportsCocoa;
       
   150     if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR)
       
   151         supportsCocoa = FALSE;
       
   152     
       
   153     if (!supportsCocoa)
       
   154         return NPERR_INCOMPATIBLE_VERSION_ERROR;
       
   155     
       
   156     browser->setvalue(instance, NPPVpluginEventModel, (void *)NPEventModelCocoa);
       
   157     
       
   158     for (int16_t i = 0; i < argc; i++) {
       
   159         if (strcasecmp(argn[i], "movieurl") == 0) {
       
   160             NSString *urlString = [NSString stringWithUTF8String:argv[i]];
       
   161             if (urlString) 
       
   162                 obj->movieURL = [[NSURL URLWithString:urlString] retain];
       
   163             break;
       
   164         }
       
   165         
       
   166     }
       
   167     
       
   168     return NPERR_NO_ERROR;
       
   169 }
       
   170 
       
   171 NPError NPP_Destroy(NPP instance, NPSavedData** save)
       
   172 {
       
   173     // Free per-instance storage
       
   174     PluginObject *obj = instance->pdata;
       
   175 
       
   176     [obj->movie stop];
       
   177     [obj->rootLayer release];
       
   178     
       
   179     free(obj);
       
   180     
       
   181     return NPERR_NO_ERROR;
       
   182 }
       
   183 
       
   184 NPError NPP_SetWindow(NPP instance, NPWindow* window)
       
   185 {
       
   186     PluginObject *obj = instance->pdata;
       
   187     obj->window = *window;
       
   188 
       
   189     return NPERR_NO_ERROR;
       
   190 }
       
   191  
       
   192 
       
   193 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
       
   194 {
       
   195     *stype = NP_ASFILEONLY;
       
   196     return NPERR_NO_ERROR;
       
   197 }
       
   198 
       
   199 NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
       
   200 {
       
   201     return NPERR_NO_ERROR;
       
   202 }
       
   203 
       
   204 int32_t NPP_WriteReady(NPP instance, NPStream* stream)
       
   205 {
       
   206     return 0;
       
   207 }
       
   208 
       
   209 int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer)
       
   210 {
       
   211     return 0;
       
   212 }
       
   213 
       
   214 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
       
   215 {
       
   216 }
       
   217 
       
   218 void NPP_Print(NPP instance, NPPrint* platformPrint)
       
   219 {
       
   220 
       
   221 }
       
   222 
       
   223 static void handleMouseDown(PluginObject *obj, NPCocoaEvent *event)
       
   224 {
       
   225     CGPoint point = CGPointMake(event->data.mouse.pluginX, 
       
   226                                 // Flip the y coordinate
       
   227                                 obj->window.height - event->data.mouse.pluginY);
       
   228     
       
   229     obj->mouseDownLayer = [obj->rootLayer hitTest:point];
       
   230     if (obj->mouseDownLayer == obj->controllerLayer) {
       
   231         [obj->controllerLayer handleMouseDown:[obj->rootLayer convertPoint:point toLayer:obj->controllerLayer]];
       
   232         return;
       
   233     }    
       
   234 }
       
   235 
       
   236 static void togglePlayPause(PluginObject *obj)
       
   237 {
       
   238     if (!obj->movie)
       
   239         return;
       
   240     
       
   241     if ([obj->movie rate] == 0)
       
   242         [obj->movie play];
       
   243     else
       
   244         [obj->movie stop];
       
   245 
       
   246 }
       
   247 
       
   248 static void handleMouseUp(PluginObject *obj, NPCocoaEvent *event)
       
   249 {
       
   250     CGPoint point = CGPointMake(event->data.mouse.pluginX, 
       
   251                                 // Flip the y coordinate
       
   252                                 obj->window.height - event->data.mouse.pluginY);
       
   253 
       
   254     CALayer *mouseDownLayer = obj->mouseDownLayer;
       
   255     obj->mouseDownLayer = nil;
       
   256     if (mouseDownLayer == obj->controllerLayer) {
       
   257         [obj->controllerLayer handleMouseUp:[obj->rootLayer convertPoint:point toLayer:obj->controllerLayer]];
       
   258         return;
       
   259     }
       
   260 }
       
   261 
       
   262 static void handleMouseDragged(PluginObject *obj, NPCocoaEvent *event)
       
   263 {
       
   264     CGPoint point = CGPointMake(event->data.mouse.pluginX, 
       
   265                                 // Flip the y coordinate
       
   266                                 obj->window.height - event->data.mouse.pluginY);
       
   267     
       
   268     if (obj->mouseDownLayer == obj->controllerLayer) {
       
   269         [obj->controllerLayer handleMouseDragged:[obj->rootLayer convertPoint:point toLayer:obj->controllerLayer]];
       
   270         return;
       
   271     }    
       
   272 }
       
   273 
       
   274 static void handleMouseEntered(PluginObject *obj)
       
   275 {
       
   276     // Show the controller layer.
       
   277     obj->controllerLayer.opacity = 1.0;
       
   278 }
       
   279 
       
   280 static void handleMouseExited(PluginObject *obj)
       
   281 {
       
   282     // Hide the controller layer if the movie is playing.
       
   283     if ([obj->movie rate])
       
   284         obj->controllerLayer.opacity = 0.0;
       
   285 }
       
   286 
       
   287 static int handleKeyDown(PluginObject *obj, NPCocoaEvent *event)
       
   288 {
       
   289     NSString *characters = (NSString *)event->data.key.characters;
       
   290     
       
   291     if ([characters length] == 1 && [characters characterAtIndex:0] == ' ') {
       
   292         togglePlayPause(obj);
       
   293         return 1;
       
   294     }
       
   295     
       
   296     return 0;
       
   297 }
       
   298 
       
   299 
       
   300 static int handleScrollEvent(PluginObject *obj, NPCocoaEvent *event)
       
   301 {
       
   302     double delta = event->data.mouse.deltaY;
       
   303     if (delta < 0)
       
   304         [obj->movie stepForward];
       
   305     else
       
   306         [obj->movie stepBackward];
       
   307     return 0;
       
   308 }
       
   309 
       
   310 
       
   311 
       
   312 int16_t NPP_HandleEvent(NPP instance, void* event)
       
   313 {
       
   314     PluginObject *obj = instance->pdata;
       
   315 
       
   316     NPCocoaEvent *cocoaEvent = event;
       
   317     
       
   318     switch(cocoaEvent->type) {
       
   319         case NPCocoaEventMouseDown:
       
   320             handleMouseDown(obj, cocoaEvent);
       
   321             return 1;
       
   322         case NPCocoaEventMouseUp:
       
   323             handleMouseUp(obj, cocoaEvent);
       
   324             return 1;
       
   325         case NPCocoaEventMouseDragged:
       
   326             handleMouseDragged(obj, cocoaEvent);
       
   327             return 1;
       
   328         case NPCocoaEventMouseEntered:
       
   329             handleMouseEntered(obj);
       
   330             return 1;
       
   331         case NPCocoaEventMouseExited:
       
   332             handleMouseExited(obj);
       
   333             return 1;
       
   334         case NPCocoaEventKeyDown:
       
   335             return handleKeyDown(obj, cocoaEvent);
       
   336         case NPCocoaEventScrollWheel:
       
   337             return handleScrollEvent(obj, cocoaEvent);
       
   338     }
       
   339     
       
   340     return 0;
       
   341 }
       
   342 
       
   343 void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
       
   344 {
       
   345 
       
   346 }
       
   347 
       
   348 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
       
   349 {
       
   350     PluginObject *obj = instance->pdata;
       
   351 
       
   352     switch (variable) {
       
   353         case NPPVpluginCoreAnimationLayer:
       
   354             if (!obj->rootLayer) {
       
   355                 // Setup layer hierarchy.
       
   356                 obj->rootLayer = [[CALayer layer] retain];
       
   357                 
       
   358                 obj->movieLayer = [QTMovieLayer layer];
       
   359                 obj->movieLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
       
   360                 [obj->rootLayer addSublayer:obj->movieLayer];
       
   361 
       
   362                 obj->controllerLayer = [MovieControllerLayer layer];
       
   363                 [obj->rootLayer addSublayer:obj->controllerLayer];
       
   364                 
       
   365                 if (obj->movieURL) {
       
   366                     NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:obj->movieURL, QTMovieURLAttribute,
       
   367                                                 [NSNumber numberWithBool:YES], QTMovieOpenForPlaybackAttribute, 
       
   368                                                 [NSNumber numberWithBool:YES], QTMovieLoopsAttribute, 
       
   369                                                 nil];
       
   370                     obj->movie = [QTMovie movieWithAttributes:attributes error:nil];
       
   371 
       
   372                     if (obj->movie) {
       
   373                         obj->movieLayer.movie = obj->movie;
       
   374                         [obj->controllerLayer setMovie:obj->movie];
       
   375                     }
       
   376                 }
       
   377                     
       
   378             }
       
   379             
       
   380             // Make sure to return a retained layer
       
   381             *((CALayer **)value) = [obj->rootLayer retain];
       
   382             
       
   383             return NPERR_NO_ERROR;
       
   384             
       
   385         default:
       
   386             return NPERR_GENERIC_ERROR;
       
   387     }
       
   388 }
       
   389 
       
   390 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
       
   391 {
       
   392     return NPERR_GENERIC_ERROR;
       
   393 }