2013-03-17 1 views
5

Sto creando un programma che può, tra l'altro, dissolvere la musica. Il problema è che altri thread/code possono mettere in pausa la musica, il che significa che anche la dissolvenza in entrata e in uscita non deve solo mettere in pausa, ma tenere a bada. Devo essere in grado di mettere in pausa il "timer" su un dispatch_after (perché questo viene chiamato quando la musica inizia a suonare per dire quando iniziare a dissolvere, che dovrebbe essere ritardato se era in pausa) e mettere in pausa una coda stesso (al fine di mettere in pausa un fade in o fade out mentre sono in dissolvenza dentro o fuori)Come mettere in pausa un dispatch_queue_t e le code create da esso

Ecco il codice (fadeIn e delayFadeOut sono entrambi chiamati all'inizio del programma):

- (void) doFadeIn: (float) incriment to: (int) volume with: (AVAudioPlayer*) thisplayer on: (dispatch_queue_t) queue{ 
    dispatch_async(queue, ^{ 
     double delayInSeconds = .1; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, queue, ^(void){ 
      thisplayer.volume = (thisplayer.volume + incriment) < volume ? thisplayer.volume + incriment : volume; 
      NSLog([[[NSNumber alloc] initWithFloat:thisplayer.volume] stringValue]); 
      if (thisplayer.volume < volume) { 
       [self doFadeIn:incriment to:volume with:thisplayer on:queue]; 
      } 
     }); 
    });  
} 

-(void) doDelayFadeOut: (float) incriment with: (AVAudioPlayer*) thisplayer on: (dispatch_queue_t) queue 
{ 
    dispatch_async(queue, ^{ 
     double delayInSeconds = .1; 
     dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
     dispatch_after(popTime, queue, ^(void){ 
      thisplayer.volume = (thisplayer.volume - incriment) > 0 ? thisplayer.volume - incriment : 0; 
      NSLog([[[NSNumber alloc] initWithFloat:thisplayer.volume] stringValue]); 
      if (thisplayer.volume > 0.0) { 
       [self doDelayFadeOut:incriment with:thisplayer on:queue]; 
      } 
     }); 
    }); 
} 

-(void) fadeIn: (AVAudioPlayer*) dFade { 
    if (dFade == nil) { 
     return; 
    } 
    dispatch_queue_t queue = dispatch_queue_create("com.cue.MainFade", NULL); 
    dispatch_async(queue, ^(void){ 
     if(dFade !=nil){ 
      double incriment = ([self relativeVolume]/[self fadeIn])/10; //incriment per .1 seconds. 
      [self doFadeIn: incriment to: [self relativeVolume] with:dFade on:dispatch_queue_create("com.cue.MainFade", 0)]; 
     } 

    }); 
} 

- (void) delayFadeOut: (AVAudioPlayer*) dFade { //d-fade should be independent of other threads 
    if (dFade == nil) { 
     return; 
    } 
    int timeRun = self.duration - self.fadeOut; 
    dispatch_queue_t queue = dispatch_queue_create("com.cue.MainFade", NULL); 
    dispatch_time_t mainPopTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeRun * NSEC_PER_SEC)); 
    printf("test"); 
    dispatch_after(mainPopTime, queue, ^(void){ 
     if(dFade !=nil){ 
      double incriment = ([dFade volume]/[self fadeOut])/10; //incriment per .1 seconds. 
      [self doDelayFadeOut:incriment with:dFade on:dispatch_queue_create("com.cue.MainFade", 0)]; 
     } 

    }); 
    if (self.cueType == 2) { 
     [self callNext]; 
    } 
} 

risposta

9

Per la tua domanda generale, la chiamata è dispatch_suspend() (insieme a dispatch_resume()). Ciò impedirà l'eventuale pianificazione di nuovi blocchi su una determinata coda. Non avrà alcun impatto sui blocchi già in esecuzione. Se si desidera mettere in pausa un blocco già pianificato e in esecuzione, è compito del codice verificare alcune condizioni e mettere in pausa.

La chiave per capire quando si utilizza questo, però, è che non c'è nulla che può "mettere in pausa il" timer "su un dispatch_after." Se dici che vuoi che qualcosa venga inviato dopo 1 secondo, verrà spedito completamente dopo 1 secondo. Ma "spedizione" non significa "correre". Significa "mettere su una coda". Se quella coda è sospesa, il blocco si bloccherà fino a quando la coda non verrà ripresa. La cosa da fare attenzione è che non vuoi che un gruppo di blocchi di dissolvenza si accumulino in coda. Se lo facessero, quando riprenderete la coda verrebbero pianificati tutti i back-to-back. Guardando il tuo codice, probabilmente non succederà, quindi questo potrebbe funzionare per te. Tieni a mente che la spedizione significa "mettere su una coda". E le code non sospese hanno i loro blocchi pianificati in ordine.

4

Per sospendere le code/annullare le operazioni, è necessario utilizzare NSOperation e NSOperationQueue anziché GCD. Vedi here.