home *** CD-ROM | disk | FTP | other *** search
- // MPEGThread.m
-
- #import <mach/mach.h> // post_allocate()
- #import <mach/mach_error.h>
- #import <dpsclient/dpsNeXT.h> // DPSAddPort()
- #import <objc/NXBundle.h>
- #import <appkit/Application.h>
- #import <appkit/Panel.h>
- // local objects
- #import "MPEGView.h"
- #import "MPEGThread.h"
-
- #define SEND_FCODE(x) \
- pkt.fcode = x; \
- mr = msg_send((msg_header_t *)&pkt, MSG_OPTION_NONE, 0); \
- if (SEND_SUCCESS != mr) \
- fprintf(stderr, "msg_send() failed with error %d\n", mr);
-
-
- @implementation MPEGThread
-
- /*** Initialization methods ***/
-
- - initSize:(int)size forView:anObject
- {
- kern_return_t kr;
-
- if (![super init])
- return nil;
- frameSize = size;
- view = anObject;
- controller = [NXApp delegate];
- if (KERN_SUCCESS != (kr = port_allocate(task_self(), &mpegPort)))
- {
- mach_error("port_allocate() failed in -initSize:forView:", kr);
- return [self free];
- }
- DPSAddPort(mpegPort, (DPSPortProc)receive_fcode, sizeof(mpegPacket),
- (void *)self, NX_MODALRESPTHRESHOLD + 1);
- return self;
- }
-
- - free
- {
- kern_return_t kr;
-
- [self abortDecode];
- DPSRemovePort(mpegPort);
- if (KERN_SUCCESS != (kr = port_deallocate(task_self(), mpegPort)))
- mach_error("port_deallocate() failed in -free", kr);
- return [super free];
- }
-
-
- /*** Instance methods and Standard C wrapper functions ***/
-
- void receive_fcode(mpegPacket *pkt, id self)
- {
- [self receiveFcode:pkt];
- }
-
- - receiveFcode:(mpegPacket *)pkt
- {
- switch (pkt->fcode)
- {
- case FCODE_ABORT:
- [self abortDecode];
- break;
- case FCODE_END:
- [view setAddress:(char *)address len:(int)len maxlen:(int)maxlen];
- [view runAgain];
- [self endDecode];
- break;
- default:
- if ([controller respondsTo:@selector(setFrameNumber:)])
- [controller setFrameNumber:pkt->fcode];
- break;
- }
- return self;
- }
-
-
- - decodeFile:(const char *)mpegFile
- {
- char *pchAlertTitle = "Error in MPEGThread method -decodeFile:";
- char command[256];
-
- // check for NULL pointer or empty string
- if (!mpegFile || !*mpegFile)
- {
- NXRunAlertPanel(pchAlertTitle, "No filename was specified.",
- gpchOK, NULL, NULL);
- return nil;
- }
- sprintf(command, "exec %s/mpegDecode %s",
- [[NXBundle mainBundle] directory], mpegFile);
- if (NULL == (ifp = popen(command, "r")))
- {
- NXRunAlertPanel(pchAlertTitle,
- "Could not create MPEG Decode process. Command:%s",
- gpchOK, NULL, NULL, command);
- return nil;
- }
- if (NULL == (buffer = malloc(frameSize)))
- {
- NXRunAlertPanel(pchAlertTitle, "Could not allocate memory.",
- gpchOK, NULL, NULL);
- pclose(ifp);
- return nil;
- }
- // REVIEW: check the following for errors returned?
- pStream = NXOpenFile(fileno(ifp), O_RDONLY);
- mStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
- [controller setFrameNumber:0];
-
- cthreadMain = cthread_fork(mpeg_thread, self);
- cthread_detach(cthreadMain);
- return self;
- }
-
- any_t mpeg_thread(any_t self)
- {
- [(MPEGThread *)self mpegThread];
- return self;
- }
-
- - mpegThread
- {
- mpegPacket pkt;
- int frameNumber;
- msg_return_t mr;
-
- pkt.h.msg_remote_port = mpegPort;
- pkt.h.msg_simple = TRUE;
- pkt.h.msg_size = sizeof(mpegPacket);
- pkt.h.msg_local_port = PORT_NULL;
- pkt.h.msg_type = MSG_TYPE_NORMAL;
-
- pkt.t.msg_type_name = MSG_TYPE_INTEGER_32;
- pkt.t.msg_type_size = 32;
- pkt.t.msg_type_number = FP_NUM_INT_DATA;
- pkt.t.msg_type_inline = TRUE;
- pkt.t.msg_type_longform = FALSE;
- pkt.t.msg_type_deallocate = FALSE;
-
- for (frameNumber = 1; 1; frameNumber++)
- {
- int bytes = frameSize;
-
- if (!(bytes = NXRead(pStream, buffer, bytes)))
- break;
- if (NXWrite(mStream, buffer, bytes) != bytes)
- {
- SEND_FCODE(FCODE_ABORT);
- fprintf(stderr, "NXWrite() failed in -mpegThread\n");
- return nil;
- }
- SEND_FCODE(frameNumber);
- }
- NXFlush(mStream);
- NXGetMemoryBuffer(mStream, &address, &len, &maxlen);
- NXCloseMemory(mStream, NX_SAVEBUFFER);
- mStream = NULL;
- SEND_FCODE(FCODE_END);
- return self;
- }
-
-
- - endDecode
- {
- kern_return_t kr;
- id result = self;
-
- if (cthreadMain)
- {
- if (KERN_SUCCESS != (kr = thread_suspend(cthread_thread(cthreadMain))))
- {
- result = nil; // error suspending thread
- mach_error("thread_suspend() failed in -endDecode", kr);
- }
- if (KERN_SUCCESS != (kr = cthread_abort(cthreadMain)))
- {
- result = nil; // error aborting thread
- mach_error("cthread_abort() failed in -endDecode", kr);
- }
- else cthreadMain = 0;
- }
- if (buffer)
- free(buffer);
- buffer = NULL;
- if (pStream)
- NXClose(pStream);
- pStream = NULL;
- if (ifp)
- pclose(ifp);
- ifp = NULL;
- return result;
- }
-
-
- - abortDecode
- {
- [self endDecode];
- if (mStream)
- NXCloseMemory(mStream, NX_FREEBUFFER);
- address = NULL, len = maxlen = 0;
- return self;
- }
-
-
- @end
-