Highlight chords (badly), nonblocking sound

This commit is contained in:
Matthias Neeracher 2006-10-08 05:56:25 +00:00
parent 50da584417
commit cbc2b31da8
13 changed files with 989 additions and 1298 deletions

Binary file not shown.

View File

@ -16,6 +16,9 @@
- (NSString *) stringValue; - (NSString *) stringValue;
- (void) setStringValue:(NSString*)val; - (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val; - (BOOL) validValue:(NSString*)val;
- (void) moveToNext;
- (void) moveToPrev;
- (void) highlightCursor;
@end @end

View File

@ -24,6 +24,18 @@
return YES; return YES;
} }
- (void) moveToNext
{
}
- (void) moveToPrev
{
}
- (void) highlightCursor
{
}
@end @end
@implementation VLDocument @implementation VLDocument

View File

@ -40,8 +40,14 @@ enum VLRegion {
kRegionLyrics kRegionLyrics
}; };
enum VLRecalc {
kNoRecalc,
kRecalc,
kFirstRecalc
};
@interface VLSheetView : NSView { @interface VLSheetView : NSView {
BOOL fNeedsRecalc; VLRecalc fNeedsRecalc;
BOOL fIsRest; BOOL fIsRest;
float fClefKeyW; float fClefKeyW;
float fMeasureW; float fMeasureW;
@ -58,7 +64,6 @@ enum VLRegion {
VLFract fCursorAt; VLFract fCursorAt;
int fCursorPitch; int fCursorPitch;
BOOL fShowFieldEditor;
IBOutlet id fFieldEditor; IBOutlet id fFieldEditor;
} }

View File

@ -79,15 +79,19 @@ static float sFlatPos[] = {
[sMusic[i] setSize:sz]; [sMusic[i] setSize:sz];
} }
} }
fNeedsRecalc = YES; fNeedsRecalc = kFirstRecalc;
fIsRest = NO; fIsRest = NO;
fShowFieldEditor = NO;
fDisplayScale = 1.0f; fDisplayScale = 1.0f;
fCursorPitch = VLNote::kNoPitch; fCursorPitch = VLNote::kNoPitch;
} }
return self; return self;
} }
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (VLDocument *) document - (VLDocument *) document
{ {
return [[[self window] windowController] document]; return [[[self window] windowController] document];
@ -167,7 +171,6 @@ static float sFlatPos[] = {
- (void) recalculateDimensions - (void) recalculateDimensions
{ {
NSScrollView * scroll = [self enclosingScrollView]; NSScrollView * scroll = [self enclosingScrollView];
fNeedsRecalc = NO;
NSSize sz = [scroll contentSize]; NSSize sz = [scroll contentSize];
sz.width /= fDisplayScale; sz.width /= fDisplayScale;
@ -202,6 +205,16 @@ static float sFlatPos[] = {
[self setFrameSize:frameSz]; [self setFrameSize:frameSz];
[self setBoundsSize:sz]; [self setBoundsSize:sz];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
if (fNeedsRecalc == kFirstRecalc) {
NSView *dv = [scroll documentView];
NSView *cv = [scroll contentView];
[dv scrollPoint:
NSMakePoint(0.0, NSMaxY([dv frame])-NSHeight([cv bounds]))];
}
fNeedsRecalc = kNoRecalc;
} }
- (void)drawGridForSystem:(int)system - (void)drawGridForSystem:(int)system
@ -317,15 +330,16 @@ static float sFlatPos[] = {
[self drawGridForSystem:system]; [self drawGridForSystem:system];
[self drawNotesForSystem:system]; [self drawNotesForSystem:system];
[self drawChordsForSystem:system]; [self drawChordsForSystem:system];
} }
VLEditable * editable = [[self document] valueForKey: @"editTarget"];
[editable highlightCursor];
} }
- (IBAction) setKey:(id)sender - (IBAction) setKey:(id)sender
{ {
int key = [[sender selectedItem] tag]; int key = [[sender selectedItem] tag];
[[self document] setKey: key transpose: YES]; [[self document] setKey: key transpose: YES];
fNeedsRecalc = YES; fNeedsRecalc = kRecalc;
[self setNeedsDisplay: YES];
} }
- (IBAction) setTime:(id)sender - (IBAction) setTime:(id)sender
@ -333,7 +347,7 @@ static float sFlatPos[] = {
int time = [[sender selectedItem] tag]; int time = [[sender selectedItem] tag];
[[self document] setTimeNum: time >> 8 denom: time & 0xFF]; [[self document] setTimeNum: time >> 8 denom: time & 0xFF];
fNeedsRecalc = YES; fNeedsRecalc = kRecalc;
[self setNeedsDisplay: YES]; [self setNeedsDisplay: YES];
} }
@ -342,15 +356,13 @@ static float sFlatPos[] = {
int div = [[sender selectedItem] tag]; int div = [[sender selectedItem] tag];
[[self document] setDivisions: div]; [[self document] setDivisions: div];
fNeedsRecalc = YES; fNeedsRecalc = kRecalc;
[self setNeedsDisplay: YES]; [self setNeedsDisplay: YES];
} }
- (IBAction)hideFieldEditor:(id)sender - (IBAction)hideFieldEditor:(id)sender
{ {
[fFieldEditor setAction:nil]; [fFieldEditor setAction:nil];
[self setValue: [NSNumber numberWithBool:NO]
forKey: @"fShowFieldEditor"];
} }
const float kSemiFloor = -2.5f*kLineH; const float kSemiFloor = -2.5f*kLineH;
@ -480,4 +492,26 @@ static int sSemiToPitch[] = {
return [editable validValue:[fFieldEditor stringValue]]; return [editable validValue:[fFieldEditor stringValue]];
} }
- (void)controlTextDidEndEditing:(NSNotification *)note
{
VLEditable * editable = [[self document] valueForKey: @"editTarget"];
switch ([[[note userInfo] objectForKey:@"NSTextMovement"] intValue]) {
case NSTabTextMovement:
[editable moveToNext];
break;
case NSBacktabTextMovement:
[editable moveToPrev];
break;
default:
[editable autorelease];
editable = nil;
}
[[self document] setValue:editable forKey: @"editTarget"];
if (editable)
[fFieldEditor selectText:self];
[[self window] performSelectorOnMainThread:@selector(makeFirstResponder:)
withObject:(editable ? fFieldEditor : self)
waitUntilDone:NO];
}
@end @end

View File

@ -6,10 +6,34 @@
// Copyright 2006 __MyCompanyName__. All rights reserved. // Copyright 2006 __MyCompanyName__. All rights reserved.
// //
#import "VLDocument.h"
@interface VLChordEditable : VLEditable {
VLSheetView * fView;
VLSong * fSong;
int fMeasure;
VLFract fAt;
}
- (VLChordEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at;
- (NSString *) stringValue;
- (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val;
- (void) moveToNext;
- (void) moveToPrev;
- (void) highlightCursor;
@end
@interface VLSheetView (Chords) @interface VLSheetView (Chords)
- (void) editChord; - (void) editChord;
- (void) drawChordsForSystem:(int)system; - (void) drawChordsForSystem:(int)system;
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at;
@end @end

View File

@ -12,12 +12,11 @@
#import "VLModel.h" #import "VLModel.h"
#import "VLSoundOut.h" #import "VLSoundOut.h"
#import "VLDocument.h"
std::string NormalizeName(NSString* rawName) std::string NormalizeName(NSString* rawName)
{ {
std::string chordName = std::string chordName =
(const char *)[[rawName lowercaseString] UTF8String]; rawName ? (const char *)[[rawName lowercaseString] UTF8String] : "";
// //
// Normalize # and b // Normalize # and b
// //
@ -65,26 +64,9 @@ std::string NormalizeName(NSString* rawName)
@end @end
@interface VLChordEditable : VLEditable {
NSView * fView;
VLSong * fSong;
int fMeasure;
VLFract fAt;
}
- (VLChordEditable *)initWithView:(NSView *)view
song:(VLSong *)song
measure:(int)measure
at:(VLFract)at;
- (NSString *) stringValue;
- (void) setStringValue:(NSString*)val;
- (BOOL) validValue:(NSString*)val;
@end
@implementation VLChordEditable @implementation VLChordEditable
- (VLChordEditable *)initWithView:(NSView *)view - (VLChordEditable *)initWithView:(VLSheetView *)view
song:(VLSong *)song song:(VLSong *)song
measure:(int)measure measure:(int)measure
at:(VLFract)at; at:(VLFract)at;
@ -95,6 +77,8 @@ std::string NormalizeName(NSString* rawName)
fMeasure= measure; fMeasure= measure;
fAt = at; fAt = at;
[fView setNeedsDisplay: YES];
return self; return self;
} }
@ -151,6 +135,33 @@ std::string NormalizeName(NSString* rawName)
return chord.fPitch != VLNote::kNoPitch; return chord.fPitch != VLNote::kNoPitch;
} }
- (void) moveToNext
{
const VLProperties & prop = fSong->fProperties.front();
fAt = fAt+VLFraction(1,4);
if (fAt >= prop.fTime) {
fAt = VLFraction(0,4);
fMeasure = (fMeasure+1) % fSong->CountMeasures();
}
}
- (void) moveToPrev
{
if (fAt < VLFraction(1,4)) {
const VLProperties & prop = fSong->fProperties.front();
fAt = prop.fTime - VLFraction(1,4);
fMeasure =
(fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures();
} else
fAt = fAt-VLFraction(1,4);
}
- (void) highlightCursor
{
[fView highlightChordInMeasure:fMeasure at:fAt];
}
@end @end
@implementation VLSheetView (Chords) @implementation VLSheetView (Chords)
@ -236,7 +247,17 @@ std::string NormalizeName(NSString* rawName)
measure:fCursorMeasure measure:fCursorMeasure
at:fCursorAt]; at:fCursorAt];
[doc setValue:e forKey:@"editTarget"]; [doc setValue:e forKey:@"editTarget"];
[self setValue:[NSNumber numberWithBool:YES] forKey:@"fShowFieldEditor"]; [fFieldEditor selectText:self];
}
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at
{
const float kSystemY = [self systemY:measure / fMeasPerSystem];
NSRect r =
NSMakeRect([self noteXInMeasure:measure at:at],
kSystemY+kChordY, 3.0f*kNoteW, 20.0f);
[[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill];
NSRectFillUsingOperation(r, NSCompositePlusDarker);
} }
@end @end

View File

@ -42,18 +42,66 @@ private:
void Run(); void Run();
void Stop(); void Stop();
void Play(const int8_t * note, size_t numNotes = 1); void Play(const int8_t * note, size_t numNotes = 1);
protected:
friend class VLAUSoundEvent;
void Play(const int8_t * note, size_t numNotes,
UInt32 msg, UInt32 velocity);
}; };
static std::auto_ptr<VLSoundOut> sSoundOut; VLSoundEvent::~VLSoundEvent()
{
}
class VLAUSoundEvent : public VLSoundEvent {
public:
VLAUSoundEvent(VLAUSoundOut * soundOut,
const int8_t * note, size_t numNotes,
UInt32 msg, UInt32 velocity)
: fSoundOut(soundOut), fNotes(note, note+numNotes),
fMsg(msg), fVelocity(velocity)
{}
virtual void Perform();
private:
VLAUSoundOut * fSoundOut;
std::vector<int8_t> fNotes;
UInt32 fMsg;
UInt32 fVelocity;
};
void VLAUSoundEvent::Perform()
{
fSoundOut->Play(&fNotes[0], fNotes.size(), fMsg, fVelocity);
delete this;
}
void VLSoundScheduler::Schedule(VLSoundEvent * what, float when)
{
usleep((int)(1000000.0f*when));
what->Perform();
}
static std::auto_ptr<VLSoundOut> sSoundOut;
static std::auto_ptr<VLSoundScheduler> sSoundScheduler;
VLSoundOut * VLSoundOut::Instance() VLSoundOut * VLSoundOut::Instance()
{ {
if (!sSoundOut.get()) if (!sSoundOut.get()) {
sSoundOut.reset(new VLAUSoundOut); sSoundOut.reset(new VLAUSoundOut);
if (!sSoundScheduler.get())
sSoundScheduler.reset(new VLSoundScheduler);
}
return sSoundOut.get(); return sSoundOut.get();
} }
void VLSoundOut::SetScheduler(VLSoundScheduler * scheduler)
{
sSoundScheduler.reset(scheduler);
}
VLSoundOut::~VLSoundOut() VLSoundOut::~VLSoundOut()
{ {
} }
@ -149,11 +197,14 @@ void VLAUSoundOut::Play(const int8_t * note, size_t numNotes)
const UInt32 kNoteOff = kMidiMessage_NoteOff << 4 | kMidiChannelInUse; const UInt32 kNoteOff = kMidiMessage_NoteOff << 4 | kMidiChannelInUse;
const UInt32 kNoteVelocity= 127; const UInt32 kNoteVelocity= 127;
for (size_t i = 0; i<numNotes; ++i) Play(note, numNotes, kNoteOn, kNoteVelocity);
MusicDeviceMIDIEvent(fSynth, kNoteOn, note[i], kNoteVelocity, 0); sSoundScheduler.get()->Schedule(
new VLAUSoundEvent(this, note, numNotes, kNoteOff, kNoteVelocity), 0.5f);
usleep (500 * 1000); }
for (size_t i = 0; i<numNotes; ++i) void VLAUSoundOut::Play(const int8_t * note, size_t numNotes,
MusicDeviceMIDIEvent(fSynth, kNoteOff, note[i], kNoteVelocity, 0); UInt32 msg, UInt32 velocity)
{
for (size_t i = 0; i<numNotes; ++i)
MusicDeviceMIDIEvent(fSynth, msg, note[i], velocity, 0);
} }

View File

@ -9,9 +9,26 @@
#include "VLModel.h" #include "VLModel.h"
class VLSoundEvent {
protected:
VLSoundEvent() {}
public:
virtual ~VLSoundEvent();
virtual void Perform() {}
};
class VLSoundScheduler {
public:
virtual void Schedule(VLSoundEvent * what, float when);
virtual ~VLSoundScheduler() {}
};
class VLSoundOut { class VLSoundOut {
public: public:
static VLSoundOut * Instance(); static VLSoundOut * Instance();
static void SetScheduler(VLSoundScheduler * scheduler);
virtual void PlayNote(const VLNote & note) = 0; virtual void PlayNote(const VLNote & note) = 0;
virtual void PlayChord(const VLChord & chord) = 0; virtual void PlayChord(const VLChord & chord) = 0;

View File

@ -7,8 +7,10 @@
// //
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "VLSoundSched.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
[VLSoundSched setup];
return NSApplicationMain(argc, (const char **) argv); return NSApplicationMain(argc, (const char **) argv);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,7 @@
95B3E1A70960E58B000E9C0D /* Music in Resources */ = {isa = PBXBuildFile; fileRef = 95B3E1980960E58B000E9C0D /* Music */; }; 95B3E1A70960E58B000E9C0D /* Music in Resources */ = {isa = PBXBuildFile; fileRef = 95B3E1980960E58B000E9C0D /* Music */; };
95B66658096BCA1F00FE18C9 /* VLSheetViewNotes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */; }; 95B66658096BCA1F00FE18C9 /* VLSheetViewNotes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */; };
95BDA15909540BF1009F9D65 /* VLSheetView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95BDA15809540BF1009F9D65 /* VLSheetView.mm */; }; 95BDA15909540BF1009F9D65 /* VLSheetView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95BDA15809540BF1009F9D65 /* VLSheetView.mm */; };
95D44D1F0AD8BFEF00384FE5 /* VLSoundSched.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95D44D1E0AD8BFEF00384FE5 /* VLSoundSched.mm */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -68,6 +69,8 @@
95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSheetViewNotes.mm; path = Sources/VLSheetViewNotes.mm; sourceTree = "<group>"; }; 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSheetViewNotes.mm; path = Sources/VLSheetViewNotes.mm; sourceTree = "<group>"; };
95BDA15709540BF1009F9D65 /* VLSheetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLSheetView.h; path = Sources/VLSheetView.h; sourceTree = "<group>"; }; 95BDA15709540BF1009F9D65 /* VLSheetView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLSheetView.h; path = Sources/VLSheetView.h; sourceTree = "<group>"; };
95BDA15809540BF1009F9D65 /* VLSheetView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSheetView.mm; path = Sources/VLSheetView.mm; sourceTree = "<group>"; }; 95BDA15809540BF1009F9D65 /* VLSheetView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSheetView.mm; path = Sources/VLSheetView.mm; sourceTree = "<group>"; };
95D44D1D0AD8BFEF00384FE5 /* VLSoundSched.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLSoundSched.h; path = Sources/VLSoundSched.h; sourceTree = "<group>"; };
95D44D1E0AD8BFEF00384FE5 /* VLSoundSched.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLSoundSched.mm; path = Sources/VLSoundSched.mm; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -167,6 +170,8 @@
952DCD77096BBB11001C2316 /* VLSheetViewChords.mm */, 952DCD77096BBB11001C2316 /* VLSheetViewChords.mm */,
95B66656096BCA1F00FE18C9 /* VLSheetViewNotes.h */, 95B66656096BCA1F00FE18C9 /* VLSheetViewNotes.h */,
95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */, 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */,
95D44D1D0AD8BFEF00384FE5 /* VLSoundSched.h */,
95D44D1E0AD8BFEF00384FE5 /* VLSoundSched.mm */,
); );
name = Classes; name = Classes;
sourceTree = "<group>"; sourceTree = "<group>";
@ -329,6 +334,7 @@
952CBB9D095FD1CA00434E43 /* VLSoundOut.cpp in Sources */, 952CBB9D095FD1CA00434E43 /* VLSoundOut.cpp in Sources */,
952DCD78096BBB11001C2316 /* VLSheetViewChords.mm in Sources */, 952DCD78096BBB11001C2316 /* VLSheetViewChords.mm in Sources */,
95B66658096BCA1F00FE18C9 /* VLSheetViewNotes.mm in Sources */, 95B66658096BCA1F00FE18C9 /* VLSheetViewNotes.mm in Sources */,
95D44D1F0AD8BFEF00384FE5 /* VLSoundSched.mm in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -447,7 +453,7 @@
GCC_PREFIX_HEADER = Sources/Vocalese_Prefix.pch; GCC_PREFIX_HEADER = Sources/Vocalese_Prefix.pch;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
INFOPLIST_FILE = Info.plist; INFOPLIST_FILE = Resources/Info.plist;
INSTALL_PATH = "$(HOME)/Applications"; INSTALL_PATH = "$(HOME)/Applications";
PREBINDING = NO; PREBINDING = NO;
PRODUCT_NAME = Vocalese; PRODUCT_NAME = Vocalese;