Having keyboard interact with programs during input Autohotkey - keyboard

I'm trying to create a program that plays a continuous "beep" sound anytime 3 seconds have passed without any key being pressed. The beep sound continues until another key is pressed, which renews the 3 second countdown.
I want the program to run in the background while I'm typing. However, while the script is running, other programs (such as Microsoft Word) do not respond to keystrokes. I tried setting BlockInput to Off, but that didn't solve the problem. Any ideas on getting the keyboard to interact with other programs? Thanks!
loop
{
Transform, CtrlQ, Chr, 17
Input, KeyPress, L1 M T3
if KeyPress = %CtrlQ%
ExitApp
if (ErrorLevel = "Timeout")
{
Run, Beep.mp3, Hide
Input, Cont, L1
if (ErrorLevel = "Max")
{
WinClose, Beep.mp3 - SMPlayer
}
}
}

other programs (such as Microsoft Word) do not respond to keystrokes
That's because your inputs block them. Add the V option (which stands for visible), like
Input, KeyPress, L1 M T3 V
This is similar to ~ for Hotkeys

loop {
if(A_TimeIdle >= 3000) {
sleep 100
IfWinNotExist, Beep.mp3 - SMPlayer
{
Run, Beep.mp3, Hide
}
} else {
IfWinExist, Beep.mp3 - SMPlayer
{
WinClose, Beep.mp3 - SMPlayer
}
}
}
^q::
ExitApp
return
A_TimeIdle might be the right function in this case.

Related

Using Python and Arduino to change delay of light bulb via Serial

I am using an Arduino Mega and python 3.7 on Windows 10 64-bit. I am trying to make a light bulb blink using python and pyserial. I want the light bulb to stay on for a x amount of time and turn off for an y amount of time. I enter the values in a python Tkinter program: https://pastebin.com/zkRmcP60 full code. after I've entered the values I send into the Arduino via this code:
import msgpack
import serial
arduionoData = serial.Serial('com3', 9600, timeout=1)
def sendlower(*args):
try:
global arduionoData
arduionoData.write(b"1")
while arduionoData.readline().decode() != "Send Next":
pass
first = int(firstdelay.get())
arduionoData.write(msgpack.packb(first, use_bin_type=True))
except ValueError:
print("Only Positive Integers")
def senduppper(*args):
try:
global arduionoData
arduionoData.write(b"2")
while arduionoData.readline().decode() != "Send Next":
pass
second = int(seconddelay.get())
arduionoData.write(msgpack.packb(second, use_bin_type=True))
except ValueError:
print("Only Positive Integers")
The Tkinter program executes the functions above visit Pastebin for entire code.
First I specify the mode or whether or not it's going to be the on delay or the off delay changing.
With this code (Setup and other code omitted please look in the paste bin for it.)
void readdelay(){
mode = Serial.parseInt();
if (mode == 1){
delay(200);
Serial.write("Send Next");
delay1 = Serial.parseInt();
}else if (mode == 2){
delay(200);
Serial.write("Send Next");
delay2 = Serial.parseInt();
}
}
void loop() {
if (Serial.available() > 0){
readdelay();
}
}
Right now if I send in any positive number into the program it either turns off(when i send in a number for the on delay) the light completely or turns it on(when I send in a number for the off delay). My guess is that whenever the Serial.parseInt(); the function gets the wrong type of input it interprets it as a zero.
The documentation says:
If no valid digits were read when the time-out (see Serial.setTimeout()) > occurs, 0 is returned;
It seems the parseInt fails, therefor the delay is set to 0, which is why the light goes completely on or off.
Another possibility it that the arduino only recieves the first character, which means the light switches so fast you cant see it. (Issue described here)
Try printing out what value is received by the arduino. It should tell you what is happening and what direction to go to solve it.

First note played in AKSequencer is off

I am using AKSequencer to create a sequence of notes that are played by an AKMidiSampler. My problem is, at higher tempos the first note always plays with a little delay, no matter what i do.
I tried prerolling the sequence but it won't help. Substituting the AKMidiSampler with an AKSampler or a AKSamplePlayer (and using a callback track to play them) hasn't helped either, though it made me think that the problem probably resides in the sequencer or in the way I create the notes.
Here's an example of what I'm doing (I tried to make it as simple as I could):
import UIKit
import AudioKit
class ViewController: UIViewController {
let sequencer = AKSequencer()
let sampler = AKMIDISampler()
let callbackInst = AKCallbackInstrument()
var metronomeTrack : AKMusicTrack?
var callbackTrack : AKMusicTrack?
let numberOfBeats = 8
let tempo = 280.0
var startTime : TimeInterval = 0
override func viewDidLoad() {
super.viewDidLoad()
print("Begin setup.")
// Load .wav sample in AKMidiSampler
do {
try sampler.loadWav("tick")
} catch {
print("sampler.loadWav() failed")
}
// Create tracks for the sequencer and set midi outputs
metronomeTrack = sequencer.newTrack("metronomeTrack")
callbackTrack = sequencer.newTrack("callbackTrack")
metronomeTrack?.setMIDIOutput(sampler.midiIn)
callbackTrack?.setMIDIOutput(callbackInst.midiIn)
// Setup and start AudioKit
AudioKit.output = sampler
do {
try AudioKit.start()
} catch {
print("AudioKit.start() failed")
}
// Set sequencer tempo
sequencer.setTempo(tempo)
// Create the notes
var midiSequenceIndex = 0
for i in 0 ..< numberOfBeats {
// Add notes to tracks
metronomeTrack?.add(noteNumber: 60, velocity: 100, position: AKDuration(beats: Double(midiSequenceIndex)), duration: AKDuration(beats: 0.5))
callbackTrack?.add(noteNumber: MIDINoteNumber(midiSequenceIndex), velocity: 100, position: AKDuration(beats: Double(midiSequenceIndex)), duration: AKDuration(beats: 0.5))
print("Adding beat number \(i+1) at position: \(midiSequenceIndex)")
midiSequenceIndex += 1
}
// Set the callback
callbackInst.callback = {status, noteNumber, velocity in
if status == .noteOn {
let currentTime = Date().timeIntervalSinceReferenceDate
let noteDelay = currentTime - ( self.startTime + ( 60.0 / self.tempo ) * Double(noteNumber) )
print("Beat number: \(noteNumber) delay: \(noteDelay)")
} else if ( noteNumber == midiSequenceIndex - 1 ) && ( status == .noteOff) {
print("Sequence ended.\n")
self.toggleMetronomePlayback()
} else {return}
}
// Preroll the sequencer
sequencer.preroll()
print("Setup ended.\n")
}
#IBAction func playButtonPressed(_ sender: UIButton) {
toggleMetronomePlayback()
}
func toggleMetronomePlayback() {
if sequencer.isPlaying == false {
print("Playback started.")
startTime = Date().timeIntervalSinceReferenceDate
sequencer.play()
} else {
sequencer.stop()
sequencer.rewind()
}
}
}
Could anyone help? Thank you.
As Aure commented, the start up latency is a known problem. Even with preroll, there is still noticeable latency, especially at higher tempos.
But if you are using a looping sequence, I found that you can sometimes mitigate how noticeable the latency is by setting the 'starting point' of the sequence to a position after the final MIDI event, but within the loop length. If you can find a good position, you can get the latency effects out of the way before it loops back to your content.
Make sure to call setTime() before you need it (e.g., after stopping the sequence, not when you are ready to play) because the setTime()call itself can introduce about 200ms of wonkiness.
Edit:
As an afterthought, you could do the same thing on a non-looping sequence by enabling looping and using an arbitrarily long sequence length. If you needed playback to stop at the end of the MIDI content, you could do this with an AKCallbackInstrument triggered by an MIDI event placed just after the final note.
After a bit of testing I actually found out that it is not the first note that plays off but the subsequent notes that play in advance. Moreover, the amount of notes that play exactly on time when starting the sequencer depends on the set tempo.
The funny thing is that if the tempo is < 400 there will be one note played on time and the others in advance, if it is 400 <= bpm < 800 there will be two notes played correctly and the others in advance and so on, for every 400 bpm increment you get one more note played correctly.
So... since the notes are played in advance and not late, the solution that solved it for me is:
1) Use a sampler that is not connected directly to a track's midi output but has its .play() method called inside a callback.
2) Keep track of when the sequencer gets started
3) At every callback calculate when the note should play in relation to the start time and store what time it actually is, so you can then calculate the offset.
4) use the computed offset to dispatch_async after the offset your .play() method.
And that's it, I tested this on multiple devices and now all the notes play perfectly on time.
I had the same issue, preroll didn't help, but I have managed to solve it with a dedicated sampler for the first notes.
I used a delay on the other sampler, about 0.06 of a second, works like a charm.
Kind of a silly solution but it did the job and I could go on with the project :)
//This is for fixing AK bug that plays the first playback not in delay
let fixDelay = AKDelay()
fixDelay.dryWetMix = 1
fixDelay.feedback = 0
fixDelay.lowPassCutoff = 22000
fixDelay.time = 0.06
fixDelay.start()
let preDelayMixer = AKMixer()
let preFirstMixer = AKMixer()
[playbackSampler,vocalSampler] >>> preDelayMixer >>> fixDelay
[firstNoteVocalSampler, firstRoundPlaybackSampler] >>> preFirstMixer
[fixDelay,preFirstMixer] >>> endMixer

Thread.sleep activates before previoues code

This code will check if three buttons in a row have the same text. If it does, it will change color to green on those buttons and change int counter to 9. When it is past this piece of code, it will reset all buttons their original state because counter == 9.
Problem is, it will sleep before it makes the buttons green. Why is that?
int counter = 0;
private void winCheck(String sign)
{
if (jButton1.getText().equals(sign))
{
if (jButton2.getText().equals(sign))
{
if (jButton3.getText().equals(sign))
{
jButton1.setBackground(Color.GREEN);
jButton2.setBackground(Color.GREEN);
jButton3.setBackground(Color.GREEN);
counter = 9;
}
try {
Thread.sleep(1000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
// This last part to show what I mean with reset.
counter++;
if (counter == 10)
{
jButton1.setBackground(null);
jButton1.setText(" ");
counter = 0;
}
Answer by Kirill Shlenskiy (please upvote his comments):
Problem is, it will sleep before it makes the buttons green" - that is unlikely to be true. Step through your code - I bet that the button background colour value will be exactly what you expect it to be right after you set it (and before you hit Thread.sleep). You just can't see the update because your UI thread is busy waiting on the blocking Thread.sleep call to finish and not pumping. You either need an asynchronous alternative to sleep (timer for example) or a way to force the UI element to redraw immediately. – Kirill Shlenskiy Jul 10 at 13:38
I set the colour to be green but it is not drawn before I put the thread to sleep? – uranibaba Jul 11 at 8:10
#uranibaba, correct. And that's by design. The UI thread redraws the UI when it has nothing else to do. Thread.sleep does not defer the rest of the method - it blocks the thread so that it can't do anything else (i.e. redraw the UI) until the synchronous work is complete. – Kirill Shlenskiy Jul 11 at 10:43

How to increment a number and output to label

The program should count the number of correct words typed (duh), and after 60 seconds, print that value to a little label.
Does it? No. It counts to 1 and then refuses to increment.
But (and this is the fun part) when I run it in Debug mode with a breakpoint, it all works fine.
I can only figure it is some sort of variable encapsulation error (which still makes no sense).
Here's a little snippet:
private void checkWord()
{
if (txtInput.Text.ToLower() == lblQuery.Text.ToLower())
{
score++;
}
}
And here is the whole source because why not...
Programming Project.zip
http://tinyurl.com/c4af2nd
I believe you are getting white space in your comparison string. Try this to see if it works.
private void checkWord()
{
if (txtInput.Text.ToLower().Trim() == lblQuery.Text.ToLower())
{
score++;
}
}

simple counter in windows forms application C++

Just practicing my vs 2010 C++ in Windows Form Applications, I haven't done this for a very long time. I am trying to develop a simple applications where a user presses a button and then label1 begins to count everytime users presses that button1. Not sure why label1 is not incrementing by 1. Can someone tell what the problem is? Thanks in advance?
EDITED
I have found the solution and I have amended the code. I will try to close the thread and if I can't, because of I have low points, I will then try tomorrow.
namespace Counter
{
int counter = 0;
//some additional namespaces
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
counter++;
label1->Text = counter.ToString();
}
The reason why this isn't working is twofold.
The way you've written this, you only set the label text once, after you finish your "loop" (*). So the text will only change once.
Even if you move the assignment inside the loop, you're keeping the main thread busy throughout the whole function. What you want is to spawn a second thread and invoke a delegate to change the label text, something like this (C# version):
void StartCounting()
{
var thread=new Thread(()=>
{
for(int i=0;i<10;++i)
label1.Invoke((MethodInvoker)()=>{label1.Text=i.ToString();});
}
}
(*) As a side note, your entire for loop is equivalent to absolutely nothing. j will never be less than i when i starts as 0.

Resources