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

  1. // MPEGThread.m
  2.  
  3. #import <mach/mach.h>            // post_allocate()
  4. #import <mach/mach_error.h>
  5. #import <dpsclient/dpsNeXT.h>    // DPSAddPort()
  6. #import <objc/NXBundle.h>
  7. #import <appkit/Application.h>
  8. #import <appkit/Panel.h>
  9. // local objects
  10. #import "MPEGView.h"
  11. #import "MPEGThread.h"
  12.  
  13. #define SEND_FCODE(x)    \
  14.     pkt.fcode = x; \
  15.     mr = msg_send((msg_header_t *)&pkt, MSG_OPTION_NONE, 0); \
  16.     if (SEND_SUCCESS != mr) \
  17.         fprintf(stderr, "msg_send() failed with error %d\n", mr);
  18.  
  19.  
  20. @implementation MPEGThread
  21.  
  22. /*** Initialization methods ***/
  23.  
  24. - initSize:(int)size forView:anObject
  25. {
  26.     kern_return_t kr;
  27.  
  28.     if (![super init])
  29.         return nil;
  30.     frameSize = size;
  31.     view = anObject;
  32.     controller = [NXApp delegate];
  33.     if (KERN_SUCCESS != (kr = port_allocate(task_self(), &mpegPort)))
  34.     {
  35.         mach_error("port_allocate() failed in -initSize:forView:", kr);
  36.         return [self free];
  37.     }
  38.     DPSAddPort(mpegPort, (DPSPortProc)receive_fcode, sizeof(mpegPacket),
  39.             (void *)self, NX_MODALRESPTHRESHOLD + 1);
  40.     return self;
  41. }
  42.  
  43. - free
  44. {
  45.     kern_return_t kr;
  46.  
  47.     [self abortDecode];
  48.     DPSRemovePort(mpegPort);
  49.     if (KERN_SUCCESS != (kr = port_deallocate(task_self(), mpegPort)))
  50.         mach_error("port_deallocate() failed in -free", kr);
  51.     return [super free];
  52. }
  53.  
  54.  
  55. /*** Instance methods and Standard C wrapper functions ***/
  56.  
  57. void receive_fcode(mpegPacket *pkt, id self)
  58. {
  59.     [self receiveFcode:pkt];
  60. }
  61.  
  62. - receiveFcode:(mpegPacket *)pkt
  63. {
  64.     switch (pkt->fcode)
  65.     {
  66.     case FCODE_ABORT:
  67.         [self abortDecode];
  68.         break;
  69.     case FCODE_END:
  70.         [view setAddress:(char *)address len:(int)len maxlen:(int)maxlen];
  71.         [view runAgain];
  72.         [self endDecode];
  73.         break;
  74.     default:
  75.         if ([controller respondsTo:@selector(setFrameNumber:)])
  76.             [controller setFrameNumber:pkt->fcode];
  77.         break;
  78.     }
  79.     return self;
  80. }
  81.  
  82.  
  83. - decodeFile:(const char *)mpegFile
  84. {
  85.     char *pchAlertTitle = "Error in MPEGThread method -decodeFile:";
  86.     char command[256];
  87.  
  88.     // check for NULL pointer or empty string
  89.     if (!mpegFile || !*mpegFile)
  90.     {
  91.         NXRunAlertPanel(pchAlertTitle, "No filename was specified.",
  92.                 gpchOK, NULL, NULL);
  93.         return nil;
  94.     }
  95.     sprintf(command, "exec %s/mpegDecode %s",
  96.             [[NXBundle mainBundle] directory], mpegFile);
  97.     if (NULL == (ifp = popen(command, "r")))
  98.     {
  99.         NXRunAlertPanel(pchAlertTitle,
  100.                 "Could not create MPEG Decode process.  Command:%s",
  101.                 gpchOK, NULL, NULL, command);
  102.         return nil;
  103.     }
  104.     if (NULL == (buffer = malloc(frameSize)))
  105.     {
  106.         NXRunAlertPanel(pchAlertTitle, "Could not allocate memory.",
  107.                 gpchOK, NULL, NULL);
  108.         pclose(ifp);
  109.         return nil;
  110.     }
  111.     // REVIEW: check the following for errors returned?
  112.     pStream = NXOpenFile(fileno(ifp), O_RDONLY);
  113.     mStream = NXOpenMemory(NULL, 0, NX_WRITEONLY);
  114.     [controller setFrameNumber:0];
  115.  
  116.     cthreadMain = cthread_fork(mpeg_thread, self);
  117.     cthread_detach(cthreadMain);
  118.     return self;
  119. }
  120.  
  121. any_t mpeg_thread(any_t self)
  122. {
  123.     [(MPEGThread *)self mpegThread];
  124.     return self;
  125. }
  126.  
  127. - mpegThread
  128. {
  129.     mpegPacket pkt;
  130.     int frameNumber;
  131.     msg_return_t mr;
  132.  
  133.     pkt.h.msg_remote_port = mpegPort;
  134.     pkt.h.msg_simple = TRUE;
  135.     pkt.h.msg_size = sizeof(mpegPacket);
  136.     pkt.h.msg_local_port = PORT_NULL;
  137.     pkt.h.msg_type = MSG_TYPE_NORMAL;
  138.  
  139.     pkt.t.msg_type_name = MSG_TYPE_INTEGER_32;
  140.     pkt.t.msg_type_size = 32;
  141.     pkt.t.msg_type_number = FP_NUM_INT_DATA;
  142.     pkt.t.msg_type_inline = TRUE;
  143.     pkt.t.msg_type_longform = FALSE;
  144.     pkt.t.msg_type_deallocate = FALSE;
  145.  
  146.     for (frameNumber = 1; 1; frameNumber++)
  147.     {
  148.         int bytes = frameSize;
  149.  
  150.         if (!(bytes = NXRead(pStream, buffer, bytes)))
  151.             break;
  152.         if (NXWrite(mStream, buffer, bytes) != bytes)
  153.         {
  154.             SEND_FCODE(FCODE_ABORT);
  155.             fprintf(stderr, "NXWrite() failed in -mpegThread\n");
  156.             return nil;
  157.         }
  158.         SEND_FCODE(frameNumber);
  159.     }
  160.     NXFlush(mStream);
  161.     NXGetMemoryBuffer(mStream, &address, &len, &maxlen);
  162.     NXCloseMemory(mStream, NX_SAVEBUFFER);
  163.     mStream = NULL;
  164.     SEND_FCODE(FCODE_END);
  165.     return self;
  166. }
  167.  
  168.  
  169. - endDecode
  170. {
  171.     kern_return_t kr;
  172.     id result = self;
  173.  
  174.     if (cthreadMain)
  175.     {
  176.         if (KERN_SUCCESS != (kr = thread_suspend(cthread_thread(cthreadMain))))
  177.         {
  178.             result = nil;            // error suspending thread
  179.             mach_error("thread_suspend() failed in -endDecode", kr);
  180.         }
  181.         if (KERN_SUCCESS != (kr = cthread_abort(cthreadMain)))
  182.         {
  183.             result = nil;            // error aborting thread
  184.             mach_error("cthread_abort() failed in -endDecode", kr);
  185.         }
  186.         else cthreadMain = 0;
  187.     }
  188.     if (buffer)
  189.         free(buffer);
  190.     buffer = NULL;
  191.     if (pStream)
  192.         NXClose(pStream);
  193.     pStream = NULL;
  194.     if (ifp)
  195.         pclose(ifp);
  196.     ifp = NULL;
  197.     return result;
  198. }
  199.  
  200.  
  201. - abortDecode
  202. {
  203.     [self endDecode];
  204.     if (mStream)
  205.         NXCloseMemory(mStream, NX_FREEBUFFER);
  206.     address = NULL, len = maxlen = 0;
  207.     return self;
  208. }
  209.  
  210.  
  211. @end
  212.