home *** CD-ROM | disk | FTP | other *** search
/ Altsys Virtuoso 2.0K / virtuoso_20k.iso / DemoApps / Graphics / Multimedia / MPEGPlay2.3 / Source / MPEGView.m < prev    next >
Encoding:
Text File  |  1993-03-09  |  5.9 KB  |  301 lines

  1. // MPEGView.m
  2.  
  3. #import <appkit/NXImage.h>
  4. #import <appkit/graphics.h>
  5. #import <stdio.h>
  6. #import <stdlib.h>
  7. #import <appkit/NXBitmapImageRep.h>
  8. #import <appkit/Application.h>
  9. #import <appkit/Panel.h>
  10. #import <streams/streams.h>
  11. #import <sys/file.h>
  12. #import <sys/time.h>
  13. #import <string.h>
  14. #import <appkit/tiff.h>
  15. #import <dpsclient/event.h>        /* for NXEvent */
  16. #import <dpsclient/dpsNeXT.h>    // for DPSTimedEntry
  17. #import <dpsclient/psops.h>        // for PSshow()
  18. #import <objc/NXBundle.h>
  19. #import <mach/mach.h>            // vm_deallocate()
  20. #import <mach/mach_error.h>
  21. // Local Categories
  22. #import "BitmapImageRepData.h"
  23. // Local Objects
  24. #import "wraps.h"
  25. #import "Controller.h"
  26. #import "MPEGThread.h"
  27. #import "MPEGView.h"
  28.  
  29. #define PERIOD_KEY    46    /* period's character code (portable), used in checking for abort (command-period) */
  30.  
  31. @implementation MPEGView : View
  32.  
  33. /*** Initialization methods ***/
  34.  
  35. - initSize:(const NXSize *)aSize info:(mpegInfo *)pInfo
  36. {
  37.     NXRect imageRect;
  38.  
  39.     NXSetRect(&imageRect, 0.0, 0.0, aSize->width, aSize->height);
  40.     if (![super initFrame:&imageRect])
  41.         return nil;
  42.     if (nil == (theBitmap = [[NXBitmapImageRep alloc] initData:NULL
  43.             pixelsWide:(int)aSize->width
  44.             pixelsHigh:(int)aSize->height
  45.             bitsPerSample:8
  46.             samplesPerPixel:3    // (cSpace == RGB_COLOR) ? 3 : 1
  47.             hasAlpha:NO
  48.             isPlanar:NO
  49.             colorSpace:NX_RGBColorSpace
  50.             bytesPerRow:0
  51.             bitsPerPixel:0]))
  52.         return [self free];
  53.     frameLength = 3 * [theBitmap pixelsWide] * [theBitmap pixelsHigh];
  54.     if (nil == (mpegThread = [[MPEGThread alloc]
  55.             initSize:(4 + frameLength) forView:self]))
  56.     {
  57.         [theBitmap free];
  58.         return [self free];
  59.     }
  60.     data = [(NXBitmapImageRep *)theBitmap data];
  61.     theSize = *aSize;
  62.     info = pInfo;
  63.     [self newZoom:pInfo->zoom];
  64.     procIndex = (pInfo->drop << 1) + pInfo->sync;
  65.     controller = [NXApp delegate];
  66.     tag = (DPSTimedEntry)-1;
  67.     return self;
  68. }
  69.  
  70. - free
  71. {
  72.     [mpegThread free];
  73.     if ((DPSTimedEntry)-1 != tag)
  74.         DPSRemoveTimedEntry(tag);
  75.     [theBitmap setData:data];
  76.     theBitmap = [theBitmap free];
  77.     if (address && len)
  78.     {
  79.         kern_return_t kr;
  80.  
  81.         kr = vm_deallocate(task_self(), (vm_address_t)address, len);
  82.         if (KERN_SUCCESS != kr)
  83.             mach_error("vm_deallocate() failed in -free", kr);
  84.     }
  85.     address = NULL;
  86.     if (info)
  87.         free(info);
  88.     info = NULL;
  89.     return [super free];
  90. }
  91.  
  92.  
  93. /*** Standard C functions ***/
  94.  
  95. double ReadSysClock(void)
  96. {
  97.   struct timeval tv;
  98.  
  99.   gettimeofday(&tv, NULL);
  100.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  101. }
  102.  
  103.  
  104. #define DROP_FRAME    \
  105.     if (0.0 == self->now) \
  106.     { \
  107.         self->now = now; \
  108.         frameNumber = 0; \
  109.     } \
  110.     else \
  111.         frameNumber = (int)((now - self->now) * self->info->fps); \
  112.     if (frameNumber == self->frameNumber) \
  113.         return; \
  114.     self->adrs = self->address + (4 + self->frameLength) * frameNumber;
  115. #define CHECK_FOR_END    \
  116.     if (self->adrs >= self->end) \
  117.     { \
  118.         self->info->elapsedTime = ReadSysClock() - self->startTime; \
  119.         DPSRemoveTimedEntry(tag); \
  120.         self->tag = (DPSTimedEntry)-1; \
  121.         [self display]; \
  122.         self->info->frameCount = self->frameCount; \
  123.         if ([self->controller respondsTo:@selector(updateInfoPanels:)]) \
  124.             [self->controller updateInfoPanels:self]; \
  125.         return; \
  126.     }
  127. #define SLOW_STUFF    [controller setFrameNumber:frameNumber];
  128. #define SHOW_FRAME    \
  129.     [self->theBitmap setData:self->adrs]; \
  130.     [self display]; \
  131.     self->adrs += self->frameLength; \
  132.     self->frameCount++;
  133.  
  134. #define FAST
  135.  
  136. void te_none(DPSTimedEntry tag, double now, void *userData)
  137. {
  138.     MPEGView *self = userData;
  139.     int frameNumber;
  140.  
  141.     CHECK_FOR_END
  142.     frameNumber = *((long *)self->adrs)++;
  143. #ifndef FAST
  144.     SLOW_STUFF
  145. #endif
  146.     SHOW_FRAME
  147. }
  148.  
  149. void te_sync(DPSTimedEntry tag, double now, void *userData)
  150. {
  151.     MPEGView *self = userData;
  152.     int frameNumber;
  153.  
  154.     CHECK_FOR_END
  155.     frameNumber = *((long *)self->adrs)++;
  156. #ifndef FAST
  157.     SLOW_STUFF
  158. #endif
  159.     SHOW_FRAME
  160.     NXPing();
  161. }
  162.  
  163. void te_drop(DPSTimedEntry tag, double now, void *userData)
  164. {
  165.     MPEGView *self = userData;
  166.     int frameNumber;
  167.  
  168.     DROP_FRAME
  169.     CHECK_FOR_END
  170.     frameNumber = *((long *)self->adrs)++;
  171. #ifndef FAST
  172.     SLOW_STUFF
  173. #endif
  174.     SHOW_FRAME
  175. }
  176.  
  177. void te_syncNdrop(DPSTimedEntry tag, double now, void *userData)
  178. {
  179.     MPEGView *self = userData;
  180.     int frameNumber;
  181.  
  182.     DROP_FRAME
  183.     CHECK_FOR_END
  184.     frameNumber = *((long *)self->adrs)++;
  185. #ifndef FAST
  186.     SLOW_STUFF
  187. #endif
  188.     SHOW_FRAME
  189.     NXPing();
  190. }
  191.  
  192. DPSTimedEntryProc procs[] = { te_none, te_sync, te_drop, te_syncNdrop };
  193.  
  194.  
  195. /*** Instance methods ***/
  196.  
  197. - runAgain
  198. {
  199.     double period = 1.0 / info->fps;
  200.     DPSTimedEntryProc proc = procs[procIndex];
  201.  
  202.     frameCount = 0;
  203.     frameNumber = -1;
  204.     [controller setFrameNumber:0];
  205.     [controller updateInfoPanels:self];
  206.     adrs = address;
  207.     end = address + len - 4;
  208.     now = 0.0;
  209.     startTime = ReadSysClock();
  210.     tag = DPSAddTimedEntry(period, proc, self, MAX_PRIORITY);
  211.     if ((DPSTimedEntry)-1 == tag)
  212.         fprintf(stderr, "DSPAddTimedEntry() failed in -runAgain\n");
  213.     return self;
  214. }
  215.  
  216.  
  217. - runFromFile:(const char *)mpegFile
  218. {
  219.     // show something in the new window while preloading
  220.     [self banner];
  221.  
  222.     [mpegThread decodeFile:mpegFile];
  223.     return self;
  224. }
  225.  
  226.  
  227. - banner
  228. {
  229.     if ([self ready])
  230.         return nil;
  231.     [self lockFocus];
  232.     PSWpreloading(theWidth, theHeight);
  233.     [self unlockFocus];
  234.     [[self window] flushWindow];
  235.     return self;
  236. }
  237.  
  238.  
  239. - setAddress:(char *)anAddress len:(int)aLen maxlen:(int)aMaxlen
  240. {
  241.     address = anAddress;
  242.     len = aLen;
  243.     maxlen = aMaxlen;
  244.     info->totalFrames = [controller frameNumber];
  245.     return self;
  246. }
  247.  
  248. - (BOOL)ready
  249. {
  250.     return address ? YES : NO;
  251. }
  252.  
  253.  
  254. - (mpegInfo *)info
  255. {
  256.     return info;
  257. }
  258.  
  259.  
  260. - (NXSize *)newZoom:(int)zoom
  261. {
  262.     info->zoom = zoom;
  263.     theWidth = theSize.width * zoom;
  264.     theHeight = theSize.height * zoom;
  265.     NXSetRect(&theRect, 0, 0, theWidth, theHeight);
  266.     return &theSize;
  267. }
  268.  
  269. - newSync:(BOOL)flag
  270. {
  271.     info->sync = flag;
  272.     procIndex = (info->drop << 1) + info->sync;
  273.     return self;
  274. }
  275.  
  276. - newDrop:(BOOL)flag
  277. {
  278.     info->drop = flag;
  279.     procIndex = (info->drop << 1) + info->sync;
  280.     return self;
  281. }
  282.  
  283. - newFrameRate:(float)fps
  284. {
  285.     info->fps = fps;
  286.     return self;
  287. }
  288.  
  289.  
  290. /*** View Instance methods ***/
  291.  
  292. - drawSelf:(const NXRect *)rects :(int)rectCount
  293. {
  294.     [theBitmap drawIn:&theRect];
  295. //    [theBitmap draw];            // this method will not scale the bitmap
  296.     return self;
  297. }
  298.  
  299.  
  300. @end
  301.