This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Jahmaican's profile picture

os.pullEvent strange behaviour

Started by Jahmaican, 11 September 2012 - 07:19 PM
Jahmaican #1
Posted 11 September 2012 - 09:19 PM
This time it's me who ended up with a problem, or rather wondering about this phenomenon. I made the simplest "piano" program that came to my mind:
http://pastebin.com/yHaRq48A
and it works well, but I can't play the same sound more than once in a row. It's not a big deal as I can't play anyway, but I'm confused. Is this caused by pullEvent itself, or is it some issue with my code that I'm missing?
Cranium #2
Posted 11 September 2012 - 09:52 PM
The only criticisms I have are minor:
Why does Keys() get called so many times? You shouldn't have to call it both within the Play() function as well as the Keys() function. I would make the Keys() function have a while true do loop, and get rid of the calls to Keys() within play and within Keys() itself. That way, it repeats constantly, unless you press spacebar, and then have it break from the loop.
Here is a suggestion:

wire="left"
function Main()
term.clear()
term.setCursorPos(1,1)
print("PIANO! v1.0nby Jahmaicannn| |   |   | | |   |   |   | |   |n| | w | e | | | t | y | u | |   |n| |___|___| | |___|___|___| |   |n| a | s | d | f | g | h | j | k |n|___|___|___|___|___|___|___|___|nn[Press SPACE to exit]")

Keys()
end
function Keys()
--local event,p1=nil not needed if you make the next line local
while true do --start of the loop
local event,p1=os.pullEvent("char")
rs.setBundledOutput(wire,0)
if p1=="a" then
  Play("c1")
elseif p1=="s" then
  Play("d")
elseif p1=="d" then
  Play("e")
elseif p1=="f" then
  Play("f")
elseif p1=="g" then
  Play("g")
elseif p1=="h" then
  Play("a")
elseif p1=="j" then
  Play("h")
elseif p1=="k" then
  Play("c2")
elseif p1=="w" then
  Play("c1#")
elseif p1=="e" then
  Play("d#")
elseif p1=="t" then
  Play("f#")
elseif p1=="y" then
  Play("g#")
elseif p1=="u" then
  Play("a#")
elseif p1==" " then
  print("Goodbye!")
  break --breaks the loop if spacebar is pressed
end
end
end
--exit function no longer needed with the break
function Play(note)
if note=="c1" then
  output=colors.white
elseif note=="d" then
  output=colors.orange
elseif note=="e" then
  output=colors.magenta
elseif note=="f" then
  output=colors.lightBlue
elseif note=="g" then
  output=colors.yellow
elseif note=="a" then
  output=colors.lime
elseif note=="h" then
  output=colors.pink
elseif note=="c2" then
  output=colors.gray
elseif note=="c1#" then
  output=colors.lightGray
elseif note=="d#" then
  output=colors.cyan
elseif note=="f#" then
  output=colors.purple
elseif note=="g#" then
  output=colors.blue
elseif note=="a#" then
  output=colors.brown
end
end
Main()
Other than those small notes I put in there, your code looks pretty nice. This is a good idea, and looks like you implemented it well.
Jahmaican #3
Posted 11 September 2012 - 10:09 PM
Erm, your suggestions are obviously right, but it's not what I asked about. At first my code was virtually identical to your version, and I ended up with the posted one (I'd call it a debug version) trying to solve the issue. Still I can't play the same note 2 times in a row - for example I can't play D,D,D, but I can play D,D#,D.

Additionaly this lead me to an idea that one should be also able to intercept an event when a key is released, for example you get key event 57 when pressing space and -57 when releasing it.
Cranium #4
Posted 11 September 2012 - 10:12 PM
Well then without testing, the only thing I can think about, would be to add a short sleep function after each note. Not sure if that's what is causing the problem, and I'm at work. Just a suggestion though.
MysticT #5
Posted 11 September 2012 - 10:18 PM
The problem is that you need a pulse (turn on then off) to play the note, otherwise, if you only turn it on and never off, it won't detect the second one as a change (since it actually didn't change) and won't play.
So, when playing a note you should do it like this:

rs.setBundledOutput(wire, output) -- turn on
sleep(0.1) -- wait some time, so the redstone is updated and the note played
rs.setBundledOutput(wire, 0) -- turn off
Jajnick #6
Posted 11 September 2012 - 10:21 PM
Let's start with the fact, that infinite recursion is the perfect way to overflow your stack. As the previous speaker said, you should use a while true do loop.
I downloaded your code and overwrote the rs.setBundledOutput function with:

rs.setBundledOutput = function(a, :)/>/>
  print(:P/>/>
end
What I have noticed is that the redstone signal is too short, and the note blocks don't receive it. You should add the sleep function before rs.setBundledOutput(wire, 0) and everything's gonna be fine.
Jahmaican #7
Posted 11 September 2012 - 10:26 PM
That worked and actually makes sense. I tried to avoid sleep() in case any future Tchaikovsky used it and complained about lag, but well - seems like 0.05s delay is inevitable here.

Thanks for your help!