diff --git a/Art/slow.artx/Preview/preview.png b/Art/slow.artx/Preview/preview.png
new file mode 100644
index 0000000..b649e2f
Binary files /dev/null and b/Art/slow.artx/Preview/preview.png differ
diff --git a/Art/slow.artx/QuickLook/Preview.pdf b/Art/slow.artx/QuickLook/Preview.pdf
new file mode 100644
index 0000000..f68a7d9
Binary files /dev/null and b/Art/slow.artx/QuickLook/Preview.pdf differ
diff --git a/Art/slow.artx/doc.thread b/Art/slow.artx/doc.thread
new file mode 100644
index 0000000..b17f99c
Binary files /dev/null and b/Art/slow.artx/doc.thread differ
diff --git a/English.lproj/VLDocument.xib b/English.lproj/VLDocument.xib
index 2d14c48..9ef8a6e 100644
--- a/English.lproj/VLDocument.xib
+++ b/English.lproj/VLDocument.xib
@@ -101,10 +101,12 @@
Progress
+
+
+ 4FD2C68B-58C8-493C-8935-78D2E689B16F
+
+ Slow
+ Slow
+
+
+
+ 268
+ {{0, 14}, {32, 32}}
+
+
+ _NS:1491
+ YES
+
+ 67763712
+ 134217728
+
+
+ LucidaGrande
+ 13
+ 1044
+
+ _NS:1491
+
+ -2042347265
+ 134
+
+ NSImage
+ slow
+
+
+
+ 400
+ 75
+
+
+
+
+
+ {32, 32}
+ {32, 32}
+ YES
+ YES
+ 0
+ YES
+ 0
+
737868E5-40A9-4B03-B2FD-E67F9EE16B2B
@@ -238,9 +289,11 @@
>>
-
+
268
{{0, 14}, {32, 32}}
+
+
_NS:1491
1
YES
@@ -248,11 +301,7 @@
67763712
134217728
-
- LucidaGrande
- 13
- 1044
-
+
_NS:1491
-2042347265
@@ -286,9 +335,11 @@
<<
-
+
268
{{0, 14}, {32, 32}}
+
+
_NS:1491
-1
YES
@@ -403,13 +454,14 @@
-
+
+
@@ -422,6 +474,7 @@
+
@@ -1584,7 +1637,7 @@
- {{0, 0}, {2560, 1418}}
+ {{0, 0}, {1440, 878}}
{890, 428}
{10000000000000, 10000000000000}
128
@@ -1800,7 +1853,7 @@
{338, 127}
- {{0, 0}, {2560, 1418}}
+ {{0, 0}, {1440, 878}}
{213, 129}
{10000000000000, 10000000000000}
YES
@@ -2385,7 +2438,7 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
{372, 142}
- {{0, 0}, {2560, 1418}}
+ {{0, 0}, {1440, 878}}
{213, 129}
{10000000000000, 10000000000000}
YES
@@ -3757,7 +3810,7 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
{537, 336}
- {{0, 0}, {2560, 1418}}
+ {{0, 0}, {1440, 878}}
{213, 129}
{10000000000000, 10000000000000}
YES
@@ -4500,6 +4553,14 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
100528
+
+
+ playMusic:
+
+
+
+ 100533
+
@@ -6069,6 +6130,7 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
+
@@ -6184,6 +6246,27 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
PDF Window
+
+ 100529
+
+
+
+
+
+
+
+ 100530
+
+
+
+
+
+
+
+ 100531
+
+
+
@@ -6343,6 +6426,10 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
+ VLToolbarButton
+ com.apple.InterfaceBuilder.CocoaPlugin
+ com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
com.apple.InterfaceBuilder.CocoaPlugin
@@ -6478,7 +6565,7 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
- 100528
+ 100533
@@ -6865,6 +6952,7 @@ AAAAAAAAAAAAAHRleHQAAAAAQ29weXJpZ2h0IEFwcGxlIENvbXB1dGVyLCBJbmMuLCAyMDA1AAAAAA
{512, 512}
{512, 512}
{512, 512}
+ {512, 512}
{128, 128}
{512, 512}
{512, 512}
diff --git a/Resources/slow.icns b/Resources/slow.icns
new file mode 100644
index 0000000..dc18852
Binary files /dev/null and b/Resources/slow.icns differ
diff --git a/Sources/VLSheetWindow.mm b/Sources/VLSheetWindow.mm
index d9c09a1..f98ac98 100644
--- a/Sources/VLSheetWindow.mm
+++ b/Sources/VLSheetWindow.mm
@@ -195,6 +195,16 @@
case 1: // Fwd
VLSoundOut::Instance()->Fwd();
break;
+ case 0: {
+ float slowDown = 0.5f;
+ int modifiers=
+ [NSEvent modifierFlags] & (NSShiftKeyMask|NSAlternateKeyMask|NSCommandKeyMask|NSControlKeyMask);
+ while (modifiers) {
+ slowDown *= 0.75f;
+ modifiers &= modifiers-1;
+ }
+ VLSoundOut::Instance()->Slow(slowDown); }
+ break;
case -1: // Rew
VLSoundOut::Instance()->Bck();
break;
diff --git a/Sources/VLSoundOut.cpp b/Sources/VLSoundOut.cpp
index 8542594..2fa5ed8 100644
--- a/Sources/VLSoundOut.cpp
+++ b/Sources/VLSoundOut.cpp
@@ -37,6 +37,7 @@ public:
virtual void SetPlayRate(float rate);
virtual void Fwd();
virtual void Bck();
+ virtual void Slow(float rate);
virtual void SetMelodyState(MelodyState state);
virtual ~VLAUSoundOut();
@@ -56,6 +57,7 @@ private:
MusicTimeStamp fMusicLength;
bool fRunning;
bool fForward;
+ float fPlayRate;
dispatch_source_t fMusicPoll;
void Play(const int8_t * note, size_t numNotes = 1);
@@ -75,6 +77,39 @@ private:
OSType fDataFormat;
};
+class VLResetTimer {
+public:
+ VLResetTimer(int64_t interval, void (^block)());
+ ~VLResetTimer();
+
+ void Prime();
+private:
+ dispatch_source_t fTimer;
+ int64_t fInterval;
+ void (^fBlock)();
+};
+
+VLResetTimer::VLResetTimer(int64_t interval, void (^block)())
+ : fInterval(interval), fBlock(Block_copy(block))
+{
+ fTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
+ dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
+ dispatch_source_set_event_handler(fTimer, fBlock);
+ dispatch_source_set_timer(fTimer, DISPATCH_TIME_FOREVER, INT64_MAX, 1000*NSEC_PER_USEC);
+ dispatch_resume(fTimer);
+}
+
+VLResetTimer::~VLResetTimer()
+{
+ Block_release(fBlock);
+}
+
+void VLResetTimer::Prime()
+{
+ dispatch_source_set_timer(fTimer, dispatch_time(DISPATCH_TIME_NOW, fInterval),
+ INT64_MAX, 10*NSEC_PER_MSEC);
+}
+
VLSoundEvent::~VLSoundEvent()
{
}
@@ -211,6 +246,7 @@ void VLAUSoundOut::PlaySequence(MusicSequence music)
fMusic = music;
fMusicLength = SequenceLength(music);
+ fPlayRate = 1.0;
R(MusicSequenceSetAUGraph(fMusic, fGraph));
R(MusicPlayerSetSequence(fPlayer, fMusic));
@@ -248,11 +284,12 @@ void VLAUSoundOut::SetPlayRate(float rate)
MusicSequenceReverse(fMusic);
MusicPlayerSetTime(fPlayer, fMusicLength - rightNow);
}
- MusicPlayerSetPlayRateScalar(fPlayer, fabsf(rate));
+ fPlayRate = fabsf(rate);
+ MusicPlayerSetPlayRateScalar(fPlayer, fPlayRate);
}
-static MusicTimeStamp sLastSkip = 0.0;
-static dispatch_source_t sResetTimer;
+static MusicTimeStamp sLastSkip = 0.0;
+static VLResetTimer * sSkipResetTimer;
void VLAUSoundOut::SkipTimeInterval()
{
@@ -260,17 +297,11 @@ void VLAUSoundOut::SkipTimeInterval()
MusicPlayerGetTime(fPlayer, &time);
time += sLastSkip;
sLastSkip *= 1.1;
- if (!sResetTimer) {
- sResetTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
- dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
- dispatch_source_set_event_handler(sResetTimer, ^{
+ if (!sSkipResetTimer)
+ sSkipResetTimer = new VLResetTimer(500*NSEC_PER_MSEC, ^{
sLastSkip = 0.0;
});
- dispatch_source_set_timer(sResetTimer, DISPATCH_TIME_FOREVER, INT64_MAX, 1000*NSEC_PER_USEC);
- dispatch_resume(sResetTimer);
- }
- dispatch_source_set_timer(sResetTimer, dispatch_time(DISPATCH_TIME_NOW, 500*NSEC_PER_MSEC),
- INT64_MAX, 10*NSEC_PER_MSEC);
+ sSkipResetTimer->Prime();
MusicPlayerSetTime(fPlayer, time);
}
@@ -288,6 +319,18 @@ void VLAUSoundOut::Bck()
SkipTimeInterval();
}
+static VLResetTimer * sSlowResetTimer;
+
+void VLAUSoundOut::Slow(float rate)
+{
+ if (!sSlowResetTimer)
+ sSlowResetTimer = new VLResetTimer(500*NSEC_PER_MSEC, ^{
+ MusicPlayerSetPlayRateScalar(fPlayer, fPlayRate);
+ });
+ sSlowResetTimer->Prime();
+ MusicPlayerSetPlayRateScalar(fPlayer, fPlayRate*rate);
+}
+
void VLAUSoundOut::Stop(bool pause)
{
MusicPlayerStop(fPlayer);
diff --git a/Sources/VLSoundOut.h b/Sources/VLSoundOut.h
index 6ca7783..e4686b9 100644
--- a/Sources/VLSoundOut.h
+++ b/Sources/VLSoundOut.h
@@ -48,6 +48,7 @@ public:
virtual void SetPlayRate(float rate) = 0;
virtual void Fwd() = 0;
virtual void Bck() = 0;
+ virtual void Slow(float rate) = 0;
enum MelodyState {
kMelodyMute,
kMelodyRegular,
diff --git a/VocalEasel.xcodeproj/project.pbxproj b/VocalEasel.xcodeproj/project.pbxproj
index 196ee97..e7d632f 100644
--- a/VocalEasel.xcodeproj/project.pbxproj
+++ b/VocalEasel.xcodeproj/project.pbxproj
@@ -118,6 +118,7 @@
95AC700514099C64007EA050 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95AC700314099C64007EA050 /* AudioUnit.framework */; };
95AC700714099CF0007EA050 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95AC700614099CF0007EA050 /* Quartz.framework */; };
95AC70091409A291007EA050 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95AC70081409A291007EA050 /* Carbon.framework */; };
+ 95B2C10F141D154B00C96B56 /* slow.icns in Resources */ = {isa = PBXBuildFile; fileRef = 95B2C10E141D154B00C96B56 /* slow.icns */; };
95B3E1A70960E58B000E9C0D /* Music in Resources */ = {isa = PBXBuildFile; fileRef = 95B3E1980960E58B000E9C0D /* Music */; };
95B66658096BCA1F00FE18C9 /* VLSheetViewNotes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95B66657096BCA1F00FE18C9 /* VLSheetViewNotes.mm */; };
95BDA15909540BF1009F9D65 /* VLSheetView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95BDA15809540BF1009F9D65 /* VLSheetView.mm */; };
@@ -335,6 +336,7 @@
95AC700314099C64007EA050 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/AudioUnit.framework; sourceTree = DEVELOPER_DIR; };
95AC700614099CF0007EA050 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Quartz.framework; sourceTree = DEVELOPER_DIR; };
95AC70081409A291007EA050 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/Carbon.framework; sourceTree = DEVELOPER_DIR; };
+ 95B2C10E141D154B00C96B56 /* slow.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = slow.icns; path = Resources/slow.icns; sourceTree = ""; };
95B3E1980960E58B000E9C0D /* Music */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Music; path = Resources/Music; sourceTree = ""; };
95B66653096BC6A100FE18C9 /* VLSheetViewInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = VLSheetViewInternal.h; path = Sources/VLSheetViewInternal.h; sourceTree = ""; };
95B66656096BCA1F00FE18C9 /* VLSheetViewNotes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLSheetViewNotes.h; path = Sources/VLSheetViewNotes.h; sourceTree = ""; };
@@ -574,6 +576,7 @@
953F4B70140B041800C627F9 /* Icons */ = {
isa = PBXGroup;
children = (
+ 95B2C10E141D154B00C96B56 /* slow.icns */,
953F4B6C140B040000C627F9 /* next.icns */,
953F4B6D140B040000C627F9 /* prev.icns */,
953F4B6A140AFF2A00C627F9 /* display.icns */,
@@ -1039,6 +1042,7 @@
953F4B6B140AFF2A00C627F9 /* display.icns in Resources */,
953F4B6E140B040100C627F9 /* next.icns in Resources */,
953F4B6F140B040100C627F9 /* prev.icns in Resources */,
+ 95B2C10F141D154B00C96B56 /* slow.icns in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};