Play selection / cursor

This commit is contained in:
Matthias Neeracher 2011-09-11 23:27:53 +02:00
parent 72c4ac4d2b
commit 19c8663dcd
11 changed files with 151 additions and 47 deletions

View File

@ -11,6 +11,7 @@
#import "VLModel.h"
#import <Cocoa/Cocoa.h>
#import "VLKeyValueUndo.h"
#import <AudioToolbox/AudioToolbox.h>
@class VLSheetWindow;
@ -56,7 +57,7 @@ enum {
NSMutableDictionary*validTmpFiles;
int repeatVolta;
bool brandNew;
bool hasMusicSequence;
MusicSequence musicSequence;
VLSheetWindow * sheetWin;
VLKeyValueUndo* undo;
VLKeyValueUndo* staffMetrics;

View File

@ -102,7 +102,7 @@
vcsWrapper = nil;
repeatVolta = 2;
brandNew = true;
hasMusicSequence = false;
musicSequence = nil;
playRate = 1.0;
validTmpFiles = [[NSMutableDictionary alloc] initWithCapacity:10];
[self setHasUndoManager:YES];
@ -138,7 +138,7 @@
- (void)updateChangeCount:(NSDocumentChangeType)changeType
{
hasMusicSequence = false;
musicSequence = nil;
[validTmpFiles removeAllObjects];
[super updateChangeCount:changeType];
}
@ -458,15 +458,16 @@
- (void) playSong
{
if (hasMusicSequence) {
if (musicSequence) {
void (^finalizer)() = [sheetWin willPlaySequence:musicSequence];
VLSoundOut::Instance()->PlaySequence(NULL);
finalizer();
} else {
[self createTmpFileWithExtension:@"mid" ofType:VLMIDIType];
MusicSequence music;
NewMusicSequence(&music);
NewMusicSequence(&musicSequence);
MusicSequenceFileLoad(music, (CFURLRef)[self fileURLWithExtension:@"mid"],
MusicSequenceFileLoad(musicSequence, (CFURLRef)[self fileURLWithExtension:@"mid"],
0, 0);
size_t countIn = 0;
@ -477,14 +478,14 @@
case 0x608:
countIn = 2;
}
VLMIDIWriter annotate(music, countIn);
VLMIDIWriter annotate(musicSequence, countIn);
annotate.Visit(*song);
hasMusicSequence = true;
[sheetWin willPlaySequence:music];
baseTempo = songTempo;
VLSoundOut::Instance()->SetPlayRate(playRate);
VLSoundOut::Instance()->PlaySequence(music);
void (^finalizer)() = [sheetWin willPlaySequence:musicSequence];
VLSoundOut::Instance()->SetPlayRate(playRate);
VLSoundOut::Instance()->PlaySequence(musicSequence);
finalizer();
}
[self setPlayElements:[self playElements]];
}
@ -494,7 +495,7 @@
NSString * savedGroove = songGroove;
[validTmpFiles removeObjectForKey:@"mma"];
[validTmpFiles removeObjectForKey:@"mid"];
hasMusicSequence = false;
musicSequence = nil;
songGroove = groove;
previewRange = sections;
playElements |= kVLPlayGroovePreview;
@ -503,7 +504,7 @@
songGroove = savedGroove;
[validTmpFiles removeObjectForKey:@"mma"];
[validTmpFiles removeObjectForKey:@"mid"];
hasMusicSequence = false;
musicSequence = nil;
}
- (NSPrintOperation *)printOperationWithSettings:(NSDictionary *)printSettings

View File

@ -11,6 +11,50 @@
#include "VLMIDIWriter.h"
#include <AudioToolbox/AudioToolbox.h>
VLMIDIUtilities::VLMIDIUtilities(MusicSequence music)
: fMusic(music)
{
}
MusicTimeStamp VLMIDIUtilities::Length()
{
UInt32 ntracks;
MusicSequenceGetTrackCount(fMusic, &ntracks);
MusicTimeStamp sequenceLength = 0;
for (UInt32 i = 0; i < ntracks; ++i) {
MusicTrack track;
MusicTimeStamp trackLength;
UInt32 propsize = sizeof(MusicTimeStamp);
MusicSequenceGetIndTrack(fMusic, i, &track);
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
&trackLength, &propsize);
sequenceLength = std::max(sequenceLength, trackLength);
}
return sequenceLength;
}
MusicTimeStamp VLMIDIUtilities::Find(VLLocation at)
{
UInt32 ntracks;
MusicSequenceGetTrackCount(fMusic, &ntracks);
MusicTrack track;
MusicSequenceGetIndTrack(fMusic, ntracks-1, &track);
MusicEventIterator iter;
NewMusicEventIterator(track, &iter);
Boolean hasEvent;
while (!MusicEventIteratorHasCurrentEvent(iter, &hasEvent) && hasEvent) {
MusicTimeStamp ts;
MusicEventType ty;
const VLMIDIUserEvent * data;
UInt32 sz;
MusicEventIteratorGetEventInfo(iter, &ts, &ty, (const void **)&data, &sz);
if (ty == kMusicEventType_User && data->fAt >= at)
return ts;
MusicEventIteratorNextEvent(iter);
}
return Length();
}
struct VLMetaEvent : MIDIMetaEvent {
char fPadding[32];

View File

@ -20,6 +20,16 @@ struct VLMIDIUserEvent {
VLLocation fAt;
};
class VLMIDIUtilities {
public:
VLMIDIUtilities(MusicSequence music);
MusicTimeStamp Length();
MusicTimeStamp Find(VLLocation at);
public:
MusicSequence fMusic;
};
class VLMIDIWriter: public VLSongVisitor {
public:
VLMIDIWriter(MusicSequence music, size_t countIn)

View File

@ -13,6 +13,9 @@
#include <string>
#include <inttypes.h>
#ifndef __VLMODEL__
#define __VLMODEL__
#pragma mark -
#pragma mark class VLFraction
@ -497,6 +500,8 @@ protected:
void VisitChords(VLMeasure & measure);
};
#endif
// Local Variables:
// mode:C++
// End:

View File

@ -36,7 +36,8 @@
- (void)updateMenus;
- (void) willPlaySequence:(MusicSequence)music;
- (void (^)()) willPlaySequence:(MusicSequence)music;
- (void) playWasPaused;
@end

View File

@ -17,6 +17,8 @@
#import "VLSheetWindow.h"
#import "VLDocument.h"
#import "VLPitchGrid.h"
#import "VLSoundOut.h"
#import "VLMIDIWriter.h"
#pragma mark VLMeasureEditable
@ -126,6 +128,11 @@
return self;
}
- (void)dealloc
{
[fView setNeedsDisplay:YES];
}
- (void) userEvent:(const VLMIDIUserEvent *) event
{
if (event->fPitch) {
@ -583,12 +590,28 @@ inline int TimeTag(const VLProperties & prop)
[self updateGrooveMenu];
}
- (void) willPlaySequence:(MusicSequence)music
- (void (^)()) willPlaySequence:(MusicSequence)music
{
uint32_t selStart = fSelStart;
uint32_t selEnd = fSelEnd;
VLEditable * e =
[[VLPlaybackEditable alloc] initWithView:self];
[self setEditTarget:e];
MusicSequenceSetUserCallback(music, VLSequenceCallback, e);
return [Block_copy(^{
if (selEnd != kNoMeasure) {
VLMIDIUtilities locator(music);
VLLocation start = {selStart, VLFraction(0)};
VLLocation end = {selEnd, VLFraction(0)};
VLSoundOut::Instance()->SetStart(locator.Find(start));
if (selEnd > selStart) {
VLSoundOut::Instance()->SetEnd(locator.Find(end));
[self selectMeasure:selStart to:selEnd];
}
}
}) autorelease];
}
@end

View File

@ -64,7 +64,7 @@
- (void) setEditTarget:(VLEditable *)editable;
- (void) startAnimation;
- (void) stopAnimation;
- (void) willPlaySequence:(MusicSequence)music;
- (void (^)()) willPlaySequence:(MusicSequence)music;
- (void) showLogAndBeep;
@end

View File

@ -77,6 +77,8 @@
soundStopObserver = [nc addObserverForName:(NSString*)kVLSoundStoppedNotification
object:nil queue:oq usingBlock:^(NSNotification *note) {
[[[self window] toolbar] validateVisibleItems];
if (VLSoundOut::Instance()->AtBeginning())
[self setEditTarget:nil]; // Kill note cursor if we ran to end
}];
}
return self;
@ -96,8 +98,10 @@
- (void)setEditTarget:(VLEditable *)editable
{
[editTarget autorelease];
editTarget = editable;
if (editTarget != editable) {
[editTarget release];
editTarget = editable;
}
}
- (void) startAnimation
@ -125,9 +129,9 @@
[sheetView mouseMoved:event];
}
- (void) willPlaySequence:(MusicSequence)music
- (void (^)()) willPlaySequence:(MusicSequence)music
{
[sheetView willPlaySequence:music];
return [sheetView willPlaySequence:music];
}
- (IBAction) togglePlayElements:(id)sender
@ -183,7 +187,7 @@
- (IBAction) playStop:(id)sender
{
if (VLSoundOut::Instance()->Playing())
if (VLSoundOut::Instance()->Playing())
[self stop:sender];
else
[[self document] playSong];

View File

@ -9,6 +9,7 @@
//
#include "VLSoundOut.h"
#include "VLMIDIWriter.h"
#include <AudioUnit/AudioUnit.h>
@ -31,9 +32,12 @@ public:
virtual void PlayNote(const VLNote & note);
virtual void PlayChord(const VLChord & chord);
virtual void PlaySequence(MusicSequence music);
virtual void SetStart(MusicTimeStamp start);
virtual void SetEnd(MusicTimeStamp end);
virtual void Stop(bool pause);
virtual bool Playing();
virtual bool AtEnd();
virtual bool AtBeginning();
virtual void SetPlayRate(float rate);
virtual void Fwd();
virtual void Bck();
@ -47,16 +51,16 @@ protected:
void InitSoundOutput(bool fileOutput);
virtual void SetupOutput(AUNode outputNode);
MusicTimeStamp SequenceLength(MusicSequence music);
void SkipTimeInterval();
AUGraph fGraph;
MusicPlayer fPlayer;
private:
MusicSequence fMusic;
MusicTimeStamp fMusicLength;
MusicTimeStamp fMusicEnd;
bool fRunning;
bool fForward;
bool fWasAtEnd;
float fPlayRate;
dispatch_source_t fMusicPoll;
@ -157,7 +161,7 @@ VLSoundOut::~VLSoundOut()
}
VLAUSoundOut::VLAUSoundOut()
: fMusic(0), fRunning(false), fForward(true)
: fMusic(0), fRunning(false), fForward(true), fWasAtEnd(true)
{
InitSoundOutput(false);
fMusicPoll = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
@ -245,8 +249,9 @@ void VLAUSoundOut::PlaySequence(MusicSequence music)
Stop(false);
fMusic = music;
fMusicLength = SequenceLength(music);
fMusicEnd = VLMIDIUtilities(music).Length();
fPlayRate = 1.0;
fWasAtEnd = true;
R(MusicSequenceSetAUGraph(fMusic, fGraph));
R(MusicPlayerSetSequence(fPlayer, fMusic));
@ -256,7 +261,19 @@ void VLAUSoundOut::PlaySequence(MusicSequence music)
fRunning = true;
CFNotificationCenterPostNotification(CFNotificationCenterGetLocalCenter(), kVLSoundStartedNotification,
NULL, NULL, false);
dispatch_source_set_timer(fMusicPoll, DISPATCH_TIME_NOW, 500*NSEC_PER_MSEC, 200*NSEC_PER_MSEC);
dispatch_source_set_timer(fMusicPoll, DISPATCH_TIME_NOW, 10*NSEC_PER_MSEC, 200*NSEC_PER_MSEC);
}
void VLAUSoundOut::SetStart(MusicTimeStamp start)
{
if (fWasAtEnd)
MusicPlayerSetTime(fPlayer, start);
}
void VLAUSoundOut::SetEnd(MusicTimeStamp end)
{
if (fWasAtEnd)
fMusicEnd = end;
}
void VLAUSoundOut::SetMelodyState(VLSoundOut::MelodyState state)
@ -282,7 +299,7 @@ void VLAUSoundOut::SetPlayRate(float rate)
MusicTimeStamp rightNow;
MusicPlayerGetTime(fPlayer, &rightNow);
MusicSequenceReverse(fMusic);
MusicPlayerSetTime(fPlayer, fMusicLength - rightNow);
MusicPlayerSetTime(fPlayer, fMusicEnd - rightNow);
}
fPlayRate = fabsf(rate);
MusicPlayerSetPlayRateScalar(fPlayer, fPlayRate);
@ -343,8 +360,12 @@ void VLAUSoundOut::Slow(float rate)
void VLAUSoundOut::Stop(bool pause)
{
if (!fRunning)
return;
MusicPlayerStop(fPlayer);
fRunning = false;
fWasAtEnd = false;
if (!pause && fMusic) {
MusicPlayerSetSequence(fPlayer, NULL);
DisposeMusicSequence(fMusic);
@ -364,7 +385,14 @@ bool VLAUSoundOut::AtEnd()
{
MusicTimeStamp time;
return !MusicPlayerGetTime(fPlayer, &time) && time >= fMusicLength;
return !MusicPlayerGetTime(fPlayer, &time) && time >= fMusicEnd;
}
bool VLAUSoundOut::AtBeginning()
{
MusicTimeStamp time;
return MusicPlayerGetTime(fPlayer, &time) || !time;
}
void VLAUSoundOut::PollMusic()
@ -372,6 +400,7 @@ void VLAUSoundOut::PollMusic()
if (fRunning && AtEnd()) {
MusicPlayerSetTime(fPlayer, 0);
Stop(true);
fWasAtEnd = true;
}
}
@ -412,23 +441,6 @@ void VLAUSoundOut::Play(const int8_t * note, size_t numNotes)
PlaySequence(music);
}
MusicTimeStamp VLAUSoundOut::SequenceLength(MusicSequence music)
{
UInt32 ntracks;
MusicSequenceGetTrackCount(music, &ntracks);
MusicTimeStamp sequenceLength = 0;
for (UInt32 i = 0; i < ntracks; ++i) {
MusicTrack track;
MusicTimeStamp trackLength;
UInt32 propsize = sizeof(MusicTimeStamp);
MusicSequenceGetIndTrack(music, i, &track);
MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength,
&trackLength, &propsize);
sequenceLength = std::max(sequenceLength, trackLength);
}
return sequenceLength;
}
VLAUFileSoundOut::VLAUFileSoundOut(CFURLRef file, OSType dataFormat)
: VLAUSoundOut(true), fFile(file), fDataFormat(dataFormat)
{
@ -459,7 +471,7 @@ void VLAUFileSoundOut::PlaySequence(MusicSequence music)
UInt32 size;
UInt32 numFrames = 512;
MusicTimeStamp musicLen = SequenceLength(music)+8;
MusicTimeStamp musicLen = VLMIDIUtilities(music).Length()+8;
CFStringRef name =
CFURLCopyLastPathComponent(fFile);
CAAudioFileFormats * formats = CAAudioFileFormats::Instance();

View File

@ -42,9 +42,12 @@ public:
virtual void PlayChord(const VLChord & chord) = 0;
void PlayFile(CFDataRef file);
virtual void PlaySequence(MusicSequence music) = 0;
virtual void SetStart(MusicTimeStamp start) = 0;
virtual void SetEnd(MusicTimeStamp end) = 0;
virtual void Stop(bool pause=true) = 0;
virtual bool Playing() = 0;
virtual bool AtEnd() = 0;
virtual bool AtBeginning() = 0;
virtual void SetPlayRate(float rate) = 0;
virtual void Fwd() = 0;
virtual void Bck() = 0;