This is MPEGView.m in view mode; [Download] [Up]
// MPEGView.m #import <appkit/NXImage.h> #import <appkit/graphics.h> #import <stdio.h> #import <stdlib.h> #import <appkit/NXBitmapImageRep.h> #import <appkit/Application.h> #import <appkit/Panel.h> #import <streams/streams.h> #import <sys/file.h> #import <sys/time.h> #import <string.h> #import <appkit/tiff.h> #import <dpsclient/event.h> /* for NXEvent */ #import <dpsclient/dpsNeXT.h> // for DPSTimedEntry #import <dpsclient/psops.h> // for PSshow() #import <objc/NXBundle.h> #import <mach/mach.h> // vm_deallocate() #import <mach/mach_error.h> // Local Categories #import "BitmapImageRepData.h" // Local Objects #import "wraps.h" #import "Controller.h" #import "MPEGThread.h" #import "MPEGView.h" #define PERIOD_KEY 46 /* period's character code (portable), used in checking for abort (command-period) */ @implementation MPEGView : View /*** Initialization methods ***/ - initSize:(const NXSize *)aSize info:(mpegInfo *)pInfo { NXRect imageRect; NXSetRect(&imageRect, 0.0, 0.0, aSize->width, aSize->height); if (![super initFrame:&imageRect]) return nil; if (nil == (theBitmap = [[NXBitmapImageRep alloc] initData:NULL pixelsWide:(int)aSize->width pixelsHigh:(int)aSize->height bitsPerSample:8 samplesPerPixel:3 // (cSpace == RGB_COLOR) ? 3 : 1 hasAlpha:NO isPlanar:NO colorSpace:NX_RGBColorSpace bytesPerRow:0 bitsPerPixel:0])) return [self free]; frameLength = 3 * [theBitmap pixelsWide] * [theBitmap pixelsHigh]; if (nil == (mpegThread = [[MPEGThread alloc] initSize:(4 + frameLength) forView:self])) { [theBitmap free]; return [self free]; } data = [(NXBitmapImageRep *)theBitmap data]; theSize = *aSize; info = pInfo; [self newZoom:pInfo->zoom]; procIndex = (pInfo->drop << 1) + pInfo->sync; controller = [NXApp delegate]; tag = (DPSTimedEntry)-1; return self; } - free { [mpegThread free]; if ((DPSTimedEntry)-1 != tag) DPSRemoveTimedEntry(tag); [theBitmap setData:data]; theBitmap = [theBitmap free]; if (address && len) { kern_return_t kr; kr = vm_deallocate(task_self(), (vm_address_t)address, len); if (KERN_SUCCESS != kr) mach_error("vm_deallocate() failed in -free", kr); } address = NULL; if (info) free(info); info = NULL; return [super free]; } /*** Standard C functions ***/ double ReadSysClock(void) { struct timeval tv; gettimeofday(&tv, NULL); return (tv.tv_sec + tv.tv_usec / 1000000.0); } #define DROP_FRAME \ if (0.0 == self->now) \ { \ self->now = now; \ frameNumber = 0; \ } \ else \ frameNumber = (int)((now - self->now) * self->info->fps); \ if (frameNumber == self->frameNumber) \ return; \ self->adrs = self->address + (4 + self->frameLength) * frameNumber; #define CHECK_FOR_END \ if (self->adrs >= self->end) \ { \ self->info->elapsedTime = ReadSysClock() - self->startTime; \ DPSRemoveTimedEntry(tag); \ self->tag = (DPSTimedEntry)-1; \ [self display]; \ self->info->frameCount = self->frameCount; \ if ([self->controller respondsTo:@selector(updateInfoPanels:)]) \ [self->controller updateInfoPanels:self]; \ return; \ } #define SLOW_STUFF [controller setFrameNumber:frameNumber]; #define SHOW_FRAME \ [self->theBitmap setData:self->adrs]; \ [self display]; \ self->adrs += self->frameLength; \ self->frameCount++; #define FAST void te_none(DPSTimedEntry tag, double now, void *userData) { MPEGView *self = userData; int frameNumber; CHECK_FOR_END frameNumber = *((long *)self->adrs)++; #ifndef FAST SLOW_STUFF #endif SHOW_FRAME } void te_sync(DPSTimedEntry tag, double now, void *userData) { MPEGView *self = userData; int frameNumber; CHECK_FOR_END frameNumber = *((long *)self->adrs)++; #ifndef FAST SLOW_STUFF #endif SHOW_FRAME NXPing(); } void te_drop(DPSTimedEntry tag, double now, void *userData) { MPEGView *self = userData; int frameNumber; DROP_FRAME CHECK_FOR_END frameNumber = *((long *)self->adrs)++; #ifndef FAST SLOW_STUFF #endif SHOW_FRAME } void te_syncNdrop(DPSTimedEntry tag, double now, void *userData) { MPEGView *self = userData; int frameNumber; DROP_FRAME CHECK_FOR_END frameNumber = *((long *)self->adrs)++; #ifndef FAST SLOW_STUFF #endif SHOW_FRAME NXPing(); } DPSTimedEntryProc procs[] = { te_none, te_sync, te_drop, te_syncNdrop }; /*** Instance methods ***/ - runAgain { double period = 1.0 / info->fps; DPSTimedEntryProc proc = procs[procIndex]; frameCount = 0; frameNumber = -1; [controller setFrameNumber:0]; [controller updateInfoPanels:self]; adrs = address; end = address + len - 4; now = 0.0; startTime = ReadSysClock(); tag = DPSAddTimedEntry(period, proc, self, MAX_PRIORITY); if ((DPSTimedEntry)-1 == tag) fprintf(stderr, "DSPAddTimedEntry() failed in -runAgain\n"); return self; } - runFromFile:(const char *)mpegFile { // show something in the new window while preloading [self banner]; [mpegThread decodeFile:mpegFile]; return self; } - banner { if ([self ready]) return nil; [self lockFocus]; PSWpreloading(theWidth, theHeight); [self unlockFocus]; [[self window] flushWindow]; return self; } - setAddress:(char *)anAddress len:(int)aLen maxlen:(int)aMaxlen { address = anAddress; len = aLen; maxlen = aMaxlen; info->totalFrames = [controller frameNumber]; return self; } - (BOOL)ready { return address ? YES : NO; } - (mpegInfo *)info { return info; } - (NXSize *)newZoom:(int)zoom { info->zoom = zoom; theWidth = theSize.width * zoom; theHeight = theSize.height * zoom; NXSetRect(&theRect, 0, 0, theWidth, theHeight); return &theSize; } - newSync:(BOOL)flag { info->sync = flag; procIndex = (info->drop << 1) + info->sync; return self; } - newDrop:(BOOL)flag { info->drop = flag; procIndex = (info->drop << 1) + info->sync; return self; } - newFrameRate:(float)fps { info->fps = fps; return self; } /*** View Instance methods ***/ - drawSelf:(const NXRect *)rects :(int)rectCount { [theBitmap drawIn:&theRect]; // [theBitmap draw]; // this method will not scale the bitmap return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.