home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / SoundAndMusic / SoundKit / SoundEditor / SoundDocument.m < prev    next >
Text File  |  1992-03-27  |  6KB  |  296 lines

  1. /*
  2.  * You may freely copy, distribute and reuse the code in this example.  
  3.  * NeXT disclaims any warranty of any kind, expressed or implied, as to 
  4.  * its fitness for any particular use.
  5.  */
  6.  
  7.  
  8. #import "SoundDocument.h"
  9. #import "SoundController.h"
  10. #import "ScrollingSound.h"
  11. #import <soundkit/soundkit.h>
  12. #import <appkit/Application.h>
  13. #import <appkit/Window.h>
  14. #import <appkit/Panel.h>
  15. #import <appkit/Cursor.h>
  16. #import <stdlib.h>
  17. #import <string.h>
  18. #import <objc/NXStringTable.h>
  19.  
  20. extern int access();
  21.  
  22. @implementation SoundDocument
  23.  
  24. static void newLocat NXPoint *p)
  25. {
  26.     static count = 0;
  27.     p->x += (20.0 * count);
  28.     p->y -= (25.0 * count);
  29.     count = (count > 10)? 0 : count+1;
  30. }
  31.  
  32. - init
  33. {
  34.     NXRect theFrame;
  35.     
  36.     [super init];
  37.     [NXApp loadNibSection:"SoundDocument.nib" owner:self];
  38.     [window setDelegate:self];
  39.     [window getFrame:&theFrame];
  40.     newLocation(&theFrame.origin);
  41.     [window moveTo:theFrame.origin.x :theFrame.origin.y];
  42.     [window makeKeyAndOrderFront:nil];
  43.     mySoundView = [view docView];      /* view is the ScrollingSound 
  44.                        in the nib file */
  45.     [mySoundView setSound:[[Sound alloc] init]];
  46.     return self;
  47. }
  48.  
  49.  
  50. - setFileName:(char *)aName
  51. {
  52.     if (fileName)
  53.     free(fileName);
  54.     fileName = (char *)malloc(strlen(aName)+1);
  55.     strcpy(fileName,aName);
  56.     [window setTitleAsFilename:fileName];
  57.     return self;
  58. }
  59.  
  60. - (char *)fileName
  61. {
  62.     return fileName;
  63. }
  64.  
  65. - sound
  66. {
  67.     return [mySoundView sound];
  68. }
  69.  
  70. - saveError:(const char *)msg arg: (char *)arg;
  71. {
  72.     if (!stringTable)
  73.     stringTable = [[NXApp delegate] stringTable];
  74.     NXRunAlertPanel([stringTable valueForStringKey:"Save"],
  75.     [stringTable valueForStringKey:msg],
  76.     [stringTable valueForStringKey:"OK"],
  77.     NULL,NULL,arg);
  78.     return nil;
  79. }
  80.  
  81. - saveToFormat:templateSound fileName:(char *)fn
  82. {
  83.     if (fn) {
  84.     int err;
  85.     id theSound = [[mySoundView sound] copy];
  86.     if (templateSound && theSound) {
  87.         [theSound copySound:theSound];
  88.         err = [theSound convertToFormat:[templateSound dataFormat]
  89.                 samplingRate:[templateSound samplingRate]
  90.                 channelCount:[templateSound channelCount]];
  91.         if (err) {
  92.         /* The DSP is required for compression or decompression */
  93.         return [self saveError: 
  94.             "Cannot do format conversion %s (DSP busy?)" arg:""];
  95.         }
  96.     }
  97.     if (!access(fn, 0)) {   /* file exists */
  98.         char fileBuf[1024];
  99.         strcpy(fileBuf,fn);
  100.         strcat(fileBuf,"~");
  101.         rename(fn,fileBuf);
  102.     }
  103.     err = [theSound writeSoundfile:fn];
  104.     if (err) {
  105.         return [self saveError:"Cannot write %s" arg:fn];
  106.     }
  107.     else 
  108.       [window setDocEdited:NO];
  109.     [theSound free];
  110.     }
  111.     return self;
  112. }
  113.  
  114. - save:sender
  115. {
  116.     return [self saveToFormat:nil fileName:fileName];
  117. }
  118.  
  119. - load:sender
  120. {
  121.     if (fileName) {
  122.     id newSound, oldSound = [mySoundView sound];
  123.     newSound = [[Sound alloc] initFromSoundfile:fileName];
  124.     if (newSound) {
  125.         if (![mySoundView setSound:newSound]) { /* not displayable */
  126.         if !wSound convertToFormat:SND_FORMAT_LINEAR_16]) {
  127.             if (!stringTable)
  128.               stringTable = [[NXApp delegate] stringTable];
  129.             NXRunAlertPanel([stringTable valueForStringKey:"Open"],
  130.                     [stringTable valueForStringKey:
  131.                      "Cannot convert format for display "
  132.                      "(DSP busy?)"],
  133.                     [stringTable valueForStringKey:"OK"],
  134.                     NULL,NULL);
  135.             return nil;
  136.         } else
  137.           [mySoundView setSound:newSound];
  138.         }
  139.         [oldSound free];
  140.     }
  141.     }
  142.     [window setDocEdited:NO];
  143.     return self;
  144. }
  145.  
  146. - revertToSaved:sender
  147. {
  148.     if([window isDocEdited] && fileName
  149.             && strcmp(strrchr (fileName,'/'),"/UNTITLED")) {
  150.     if (!stringTable)
  151.         stringTable = [[NXApp delegate] stringTable];
  152.     if (NXRunAlertPanel([stringTable valueForStringKey:"Revert"],         
  153.         [stringTable valueForStringKey:"Revert to saved version"
  154.             " of %s?"],
  155.         [stringTable valueForStringKey:"Revert"],
  156.         [stringTable valueForStringKey:"Cancel"], 
  157.             0,fileName) == NX_ALERTDEFAULT)
  158.         [self load:nil];
  159.     }
  160.     return self;
  161. }
  162.   
  163. - play:sender
  164. {
  165.     [mySoundView play:sender];
  166.     return self;
  167. }
  168.  
  169. - stop:sender
  170. {
  171.     [mySoundView stop:sender];
  172.     return self;
  173. }
  174.  
  175. - pause:sender
  176. {
  177.     [mySoundView pause:sender];
  178.     return self;
  179. }
  180.  
  181. - resume:sender
  182. {
  183.     [mySoundView resume:sender];
  184.     return self;
  185. }
  186.  
  187. - record:sender
  188. {
  189.     [mySoundView record:sender];
  190.     [window setDocEdited:YES];
  191.     return self;
  192. }
  193.  
  194. - touch
  195. {
  196.     [window setDocEdited:YES];
  197.     return self;
  198. }
  199.  
  200. - setDelegate:anObject
  201. {
  202.     [mySoundView setDelegate:anObject];
  203.     return self;
  204. }
  205.  
  206. - windowDidBecomeMain:sender
  207. {
  208.     [[NXApp delegate] setDocument:self];
  209.     [window makeFirstResponder:mySoundView];
  210.     [mySoundView showCursor];
  211.     return self;
  212. }
  213.  
  214. - windowDidResignMain:sender
  215. {
  216.     id theController = [NXApp delegate];
  217.     if ([theController document] == self)
  218.     [theController setDocument:nil];
  219.     [mySoundView hideCursor];
  220.     return self;
  221. }
  222.  
  223. - windowDidMiniaturize:sender
  224. {
  225.     [mySoundView stop:sender];
  226.     [mySoundView hideCursor];
  227.     return self;
  228. }
  229.  
  230. - windowWillClose:sender
  231. {
  232.     int choice;
  233.  
  234.     if ([window isDocEdited]) {
  235.     if (!stringTable)
  236.         stringTable = [[NXApp delegate] stringTable];
  237.     choice = NXRunAlertPanel([stringTable valueForStringKey:"Close"],
  238.             [stringTable valueForStringKey:"Sound is modified.\nSave it?"],
  239.         [stringTable valueFor"ngKey:"Yes"],
  240.         [stringTable valueForStringKey:"No"],
  241.         [stringTable valueForStringKey:"Cancel"]); 
  242.     switch (choice) {
  243.         case NX_ALERTALTERNATE:
  244.         break;
  245.         case NX_ALERTDEFAULT:
  246.         [[NXApp delegate] save:nil];
  247.         break;
  248.         case NX_ALERTOTHER:
  249.         return nil;
  250.     }
  251.     }
  252.     [self windowDidResignMain:nil];
  253.     [window setDelegate:nil];
  254.     [self free];
  255.     return sender;
  256. }
  257.  
  258.  
  259. static int calcFormat(SNDSoundStruct *s)
  260. {
  261.     if (s->dataFormat == SND_FORMAT_MULAW_8)
  262.     return SND_FORMAT_MULAW_8;
  263.     else if (s->dataFormat == SND_FORMAT_INDIRECT) {
  264.     SNDSoundStruct **iBlock = (SNDSoundStruct **)s->dataLocation;
  265.  
  266.     if (*iBlock)
  267.         return (*iBlock)->dataFormat;
  268.     else
  269.         return SND_FORMAT_UNSPECIFIED;
  270.     } else
  271.     return s->dataFormat;
  272. }
  273.  
  274. - (BOOL)isRecordable
  275. {
  276.     int format;
  277.     id theSound = [mySoundView sound];
  278.     SNDSoundStruct *soundStruct = [theSound soundStruct];
  279.  
  280.     if (!soundStruct) return YES;
  281.     format = calcFormat(soundStruct);
  282.     if (format == SND_FORMAT_MULAW_8 &&
  283.         soundStruct->samplingRate == (int)SND_RATE_CODEC &&
  284.     soundStruct->channelCount == 1 )
  285.     return YES;
  286.     else
  287.     return NO;
  288. }
  289.  
  290. - (BOOL) isPlayable
  291. {
  292.     return [mySoundView isPlayable];
  293. }
  294.  
  295. @end
  296.