Problem with runtime error/segfault

Set all the alarms to something, it doesn’t matter what except sometime
in the future and out of the way except for #1. Set the first alarm on,
to maybe 2 minutes from the time you run the program. Every time I run
it I get a segfault or a runtime error. What’s wrong?

Only works if turned on before it goes off on the the day that it will

$statusChoice = [“On”, “Off”]
$hourChoice = [“00”, “01”, “02”, “03”, “04”, “05”, “06”, “07”, “08”,
“09”, “10”, “11”, “12”, “13”, “14”, “15”, “16”, “17”, “18”, “19”, “20”,
“21”, “22”, “23”]
$minChoice = [“00”, “15”, “30”, “45”]
$secChoice = [“00”, “15”, “30”, “45”]
require “Wx”
include Wx
require ‘on-off.rb’
require ‘Sets1.rb’

class SetsFrame < Frame
def initialize()
super(nil, -1, ‘Settings’)

choices = ['Alarm # 1', 'Alarm # 2', 'Alarm # 3', 'Alarm # 4']

@setsPanel = Panel.new(self)
$whichAlarm = ComboBox.new(@setsPanel, -1, 'Alarm # 1',

DEFAULT_POSITION, DEFAULT_SIZE, choices, CB_READONLY)
@editButton = Button.new(@setsPanel, -1, ‘Edit’)
evt_button(@editButton.get_id()) {|event|editButtonClick(event)}
@setsPanelSizer = BoxSizer.new(VERTICAL)
@setsPanel.set_sizer(@setsPanelSizer)
@setsPanel.sizer.add($whichAlarm, 0, GROW|ALL, 2)
@setsPanel.sizer.add(@editButton, 0, GROW|ALL, 2)
show()
end

def editButtonClick(event)
$whichAlarmVal = $whichAlarm.get_value()
if $whichAlarmVal == ‘Alarm # 1’
require ‘Sets1.rb’
elsif $whichAlarmVal == ‘Alarm # 2’
require ‘Sets2.rb’
elsif $whichAlarmVal == ‘Alarm # 3’
require ‘Sets3.rb’
elsif $whichAlarmVal == ‘Alarm # 4’
require ‘Sets4.rb’
else
# Nothings
end

EditFrame.new

end
end

class EditFrame < Frame
def initialize()
super(nil, -1, ‘Edit’)

@aPanel = Panel.new(self)
@someText = StaticText.new(@aPanel, -1, "Edit", DEFAULT_POSITION,

DEFAULT_SIZE, ALIGN_CENTER)
@comboStatus = ComboBox.new(@aPanel, -1, $statusDef,
DEFAULT_POSITION, DEFAULT_SIZE, $statusChoice, CB_READONLY)
@hourText = StaticText.new(@aPanel, -1, “Hours”)
@comboHour = ComboBox.new(@aPanel, -1, $hourDef, DEFAULT_POSITION,
DEFAULT_SIZE, $hourChoice, CB_DROPDOWN)
@minText = StaticText.new(@aPanel, -1, “Minutes”)
@comboMin = ComboBox.new(@aPanel, -1, $minDef, DEFAULT_POSITION,
DEFAULT_SIZE, $minChoice, CB_DROPDOWN)
@secText = StaticText.new(@aPanel, -1, “Seconds”)
@comboSec = ComboBox.new(@aPanel, -1, $secDef, DEFAULT_POSITION,
DEFAULT_SIZE, $secChoice, CB_DROPDOWN)
@textAlarm = StaticText.new(@aPanel, -1, “Alarm Text”)
@alarmText = TextCtrl.new(@aPanel, -1, $textDef, DEFAULT_POSITION,
DEFAULT_SIZE, TE_MULTILINE)
@dayText = StaticText.new(@aPanel, -1, “Days”)
@checkSun = CheckBox.new(@aPanel, -1, “Sunday”)
@checkMon = CheckBox.new(@aPanel, -1, “Monday”)
@checkTue = CheckBox.new(@aPanel, -1, “Tuesday”)
@checkWed = CheckBox.new(@aPanel, -1, “Wednesday”)
@checkThu = CheckBox.new(@aPanel, -1, “Thursday”)
@checkFri = CheckBox.new(@aPanel, -1, “Friday”)
@checkSat = CheckBox.new(@aPanel, -1, “Saturday”)
@saveButton = Button.new(@aPanel, -1, ‘Save’)
@defButton = Button.new(@aPanel, -1, ‘Return to Defaults’)
evt_button(@saveButton.get_id()) {|event|saveButtonClick(event)}
evt_button(@defButton.get_id()) {|event|defButtonClick(event)}
@aPanelSizer = BoxSizer.new(VERTICAL)
@aPanel.set_sizer(@aPanelSizer)
@aPanel.sizer.add(@someText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@comboStatus, 0, GROW|ALL, 2)
@aPanel.sizer.add(@hourText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@comboHour, 0, GROW|ALL, 2)
@aPanel.sizer.add(@minText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@comboMin, 0, GROW|ALL, 2)
@aPanel.sizer.add(@secText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@comboSec, 0, GROW|ALL, 2)
@aPanel.sizer.add(@textAlarm, 0, GROW|ALL, 2)
@aPanel.sizer.add(@alarmText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@dayText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkSun, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkMon, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkTue, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkWed, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkThu, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkFri, 0, GROW|ALL, 2)
@aPanel.sizer.add(@checkSat, 0, GROW|ALL, 2)
@aPanel.sizer.add(@saveButton, 0, GROW|ALL, 2)
@aPanel.sizer.add(@defButton, 0, GROW|ALL, 2)
@checkSun.set_value($sun)
@checkMon.set_value($mon)
@checkTue.set_value($tue)
@checkWed.set_value($wed)
@checkThu.set_value($thu)
@checkFri.set_value($fri)
@checkSat.set_value($sat)
show()
end

def sets1
File.open(‘Sets1.rb’, ‘w’) do |f|
f.puts “$statusDef = “#{$comboStatusVal}”
$hourDef = “#{$comboHourVal}”
$minDef = “#{$comboMinVal}”
$secDef = “#{$comboSecVal}”
$textDef = “#{$alarmTextVal}”
$sun = #{$checkSunVal}
$mon = #{$checkMonVal}
$tue = #{$checkTueVal}
$wed = #{$checkWedVal}
$thu = #{$checkThuVal}
$fri = #{$checkFriVal}
$sat = #{$checkSatVal}”
end
end

def sets2
File.open(‘Sets2.rb’, ‘w’) do |f|
f.puts “$statusDef = “#{$comboStatusVal}”
$hourDef = “#{$comboHourVal}”
$minDef = “#{$comboMinVal}”
$secDef = “#{$comboSecVal}”
$textDef = “#{$alarmTextVal}”
$sun = #{$checkSunVal}
$mon = #{$checkMonVal}
$tue = #{$checkTueVal}
$wed = #{$checkWedVal}
$thu = #{$checkThuVal}
$fri = #{$checkFriVal}
$sat = #{$checkSatVal}”
end
end

def sets3
File.open(‘Sets3.rb’, ‘w’) do |f|
f.puts “$statusDef = “#{$comboStatusVal}”
$hourDef = “#{$comboHourVal}”
$minDef = “#{$comboMinVal}”
$secDef = “#{$comboSecVal}”
$textDef = “#{$alarmTextVal}”
$sun = #{$checkSunVal}
$mon = #{$checkMonVal}
$tue = #{$checkTueVal}
$wed = #{$checkWedVal}
$thu = #{$checkThuVal}
$fri = #{$checkFriVal}
$sat = #{$checkSatVal}”
end
end

def sets4
File.open(‘Sets4.rb’, ‘w’) do |f|
f.puts “$statusDef = “#{$comboStatusVal}”
$hourDef = “#{$comboHourVal}”
$minDef = “#{$comboMinVal}”
$secDef = “#{$comboSecVal}”
$textDef = “#{$alarmTextVal}”
$sun = #{$checkSunVal}
$mon = #{$checkMonVal}
$tue = #{$checkTueVal}
$wed = #{$checkWedVal}
$thu = #{$checkThuVal}
$fri = #{$checkFriVal}
$sat = #{$checkSatVal}”
end
end

def saveButtonClick(event)
$comboStatusVal = @comboStatus.get_value()
$comboHourVal = @comboHour.get_value()
$comboMinVal = @comboMin.get_value()
$comboSecVal = @comboSec.get_value()
$alarmTextVal = @alarmText.get_value()
$checkSunVal = @checkSun.get_value()
$checkMonVal = @checkMon.get_value()
$checkTueVal = @checkTue.get_value()
$checkWedVal = @checkWed.get_value()
$checkThuVal = @checkThu.get_value()
$checkFriVal = @checkFri.get_value()
$checkSatVal = @checkSat.get_value()
if $comboStatusVal == “On”
$boolStatus = true
elsif $comboStatusVal == “Off”
$boolStatus = false
else
# Nothings
end
$whichAlarmVal = $whichAlarm.get_value()
if $whichAlarmVal == ‘Alarm # 1’
sets1
elsif $whichAlarmVal == ‘Alarm # 2’
sets2
elsif $whichAlarmVal == ‘Alarm # 3’
sets3
elsif $whichAlarmVal == ‘Alarm # 4’
sets4
else
# Nothing
end
bool1 = $onOff.fetch(0)
bool2 = $onOff.fetch(1)
bool3 = $onOff.fetch(2)
bool4 = $onOff.fetch(3)
if $whichAlarmVal == ‘Alarm # 1’
File.open(‘on-off.rb’, ‘w’) do |f|
f.puts “$onOff = [#{$boolStatus}, #{bool2}, #{bool3}, #{bool4}]”
end
elsif $whichAlarmVal == ‘Alarm # 2’
File.open(‘on-off.rb’, ‘w’) do |f|
f.puts “$onOff = [#{bool1}, #{$boolStatus}, #{bool3}, #{bool4}]”
end
elsif $whichAlarmVal == ‘Alarm # 3’
File.open(‘on-off.rb’, ‘w’) do |f|
f.puts “$onOff = [#{bool1}, #{bool2}, #{$boolStatus}, #{bool4}]”
end
elsif $whichAlarmVal == ‘Alarm # 4’
File.open(‘on-off.rb’, ‘w’) do |f|
f.puts “$onOff = [#{bool1}, #{bool2}, #{bool3}, #{$boolStatus}]”
end
else
# Nothing
end
end
def defButtonClick(event)
results = []
bool1 = $onOff.fetch(0)
bool2 = $onOff.fetch(1)
bool3 = $onOff.fetch(2)
bool4 = $onOff.fetch(3)
File.open(‘Defaults.rb’, ‘r’).each { |line| results << line }
if $whichAlarmVal == ‘Alarm # 1’
File.open(‘Sets1.rb’, ‘w’) do |f1|
f1.puts results
end
elsif $whichAlarmVal == ‘Alarm # 2’
File.open(‘Sets2.rb’, ‘w’) do |f1|
f1.puts results
end
elsif $whichAlarmVal == ‘Alarm # 3’
File.open(‘Sets3.rb’, ‘w’) do |f1|
f1.puts results
end
elsif $whichAlarmVal == ‘Alarm # 4’
File.open(‘Sets4.rb’, ‘w’) do |f1|
f1.puts results
end
else
# Nothing
end

if $whichAlarmVal == 'Alarm # 1'
  File.open('on-off.rb', 'w') do |f|
    f.puts "$onOff = [false, #{bool2}, #{bool3}, #{bool4}]"
  end
elsif $whichAlarmVal == 'Alarm # 2'
  File.open('on-off.rb', 'w') do |f|
    f.puts "$onOff = [#{bool1}, false, #{bool3}, #{bool4}]"
  end
elsif $whichAlarmVal == 'Alarm # 3'
  File.open('on-off.rb', 'w') do |f|
    f.puts "$onOff = [#{bool1}, #{bool2}, false, #{bool4}]"
  end
elsif $whichAlarmVal == 'Alarm # 4'
  File.open('on-off.rb', 'w') do |f|
    f.puts "$onOff = [#{bool1}, #{bool2}, #{bool3}, false]"
  end
else
  # Nothing
end

end
end

class AlarmFrame < Frame
def initialize()
super(nil, -1, ‘Alarm’)
@aPanel = Panel.new(self)
@someText = StaticText.new(@aPanel, -1, “Time’s up! Go to bed!”,
DEFAULT_POSITION, DEFAULT_SIZE, ALIGN_CENTER)
@stopButton = Button.new(@aPanel, -1, ‘Ok’)
evt_button(@stopButton.get_id()) {|event|stopButtonClick(event)}
@aPanelSizer = BoxSizer.new(VERTICAL)
@aPanel.set_sizer(@aPanelSizer)
@aPanel.sizer.add(@someText, 0, GROW|ALL, 2)
@aPanel.sizer.add(@stopButton, 0, GROW|ALL, 2)
Sound.play(“beep4.wav”, flags = SOUND_ASYNC|SOUND_LOOP)
show()
end

def stopButtonClick(event)
Sound.stop()
end
end

class Alarm
def initialize
$bool1 = $onOff.fetch(0)
$bool2 = $onOff.fetch(1)
$bool3 = $onOff.fetch(2)
$bool4 = $onOff.fetch(3)
end
def one
if $bool1 == true
require ‘Sets1.rb’
t = Time.now
goOff0 = $hourDef
goOff1 = $minDef
goOff2 = $secDef
sleepTime =
(goOff0.to_i3600+goOff1.to_i60+goOff2.to_i)-(t.strftime("%H").to_i3600+t.strftime("%M").to_i60+t.strftime("%S").to_i)
sleep(sleepTime)
AlarmFrame.new
else
# Nothings
end
end
def two
if $bool2 == true
require ‘Sets2.rb’
t = Time.now
goOff0 = $hourDef
goOff1 = $minDef
goOff2 = $secDef
sleepTime =
(goOff0.to_i3600+goOff1.to_i60+goOff2.to_i)-(t.strftime("%H").to_i3600+t.strftime("%M").to_i60+t.strftime("%S").to_i)
sleep(sleepTime)
AlarmFrame.new
else
# Nothings
end
end
def three
if $bool3 == true
require ‘Sets3.rb’
t = Time.now
goOff0 = $hourDef
goOff1 = $minDef
goOff2 = $secDef
sleepTime =
(goOff0.to_i3600+goOff1.to_i60+goOff2.to_i)-(t.strftime("%H").to_i3600+t.strftime("%M").to_i60+t.strftime("%S").to_i)
sleep(sleepTime)
AlarmFrame.new
else
# Nothings
end
end
def four
if $bool4 == true
require ‘Sets4.rb’
t = Time.now
goOff0 = $hourDef
goOff1 = $minDef
goOff2 = $secDef
sleepTime =
(goOff0.to_i3600+goOff1.to_i60+goOff2.to_i)-(t.strftime("%H").to_i3600+t.strftime("%M").to_i60+t.strftime("%S").to_i)
sleep(sleepTime)
AlarmFrame.new
else
# Nothings
end
end
end

class MainApp < App
def on_init
SetsFrame.new
end
end

_ = Thread.new {MainApp.new.main_loop()}
a = Thread.new {Alarm.new.one}
b = Thread.new {Alarm.new.two}
#c = Thread.new {Alarm.new.three}
#d = Thread.new {Alarm.new.four}
_.join
a.join
b.join
#c.join
#d.join

Hi Daniel

Thanks for the report. Unfortunately I couldn’t test out your code
because it requires other files that you haven’t included. We ask that
when posting a problem or bug, you simplify your code to demonstrate the
problem rather than just copying your enitre program.

http://wxruby.rubyforge.org/wiki/wiki.pl?MailingLists

I have a couple of suggestions on organisation and style that may help.
I think you could simplify your code quite a bit and that should help
iron out the bug.

My main one would be to use Wx::Timer rather than ruby Threads+sleep to
count down the time until the alarms go off. The way Ruby threads are
designed makes them ill-suited for many uses with GUI libraries, so
don’t use them unless you really have to - and here, you don’t.

def editButtonClick(event)
$whichAlarmVal = $whichAlarm.get_value()
if $whichAlarmVal == ‘Alarm # 1’
require ‘Sets1.rb’
elsif $whichAlarmVal == ‘Alarm # 2’
require ‘Sets2.rb’

Here you could make your code a lot simpler by using client_data. This
allows you to associate any normal ruby object (eg an Alarm object) with
an item in a ComboBox. So when the user clicks the edit button, you just
find the Alarm object associated with the currently selected value in
the ComboBox, and start editing it. You would then be able to handle an
arbitrary number of Alarms.

http://wxruby.rubyforge.org/doc/controlwithitems.html

@dayText = StaticText.new(@aPanel, -1, "Days")
@checkSun = CheckBox.new(@aPanel, -1, "Sunday")
@checkMon = CheckBox.new(@aPanel, -1, "Monday")
@checkTue = CheckBox.new(@aPanel, -1, "Tuesday")

A CheckListBox might be better here:
http://wxruby.rubyforge.org/doc/checklistbox.html

def sets1
File.open(‘Sets1.rb’, ‘w’) do |f|
f.puts "$statusDef = "#{$comboStatusVal}"
$hourDef = "#{$comboHourVal}"
$minDef = "#{$comboMinVal}"
There are much easier and safer ways to save an object with settings to
file. Look up “Marshal” or “YAML” for ruby - these will allow you to
save and load Alarms with no extra work.

class Alarm
def initialize

I would design your Alarm class to have attributes for the hour, minute
and second, an array for the days of the week, and a boolean to
represent whether it’s on or off.

attr_accessor :hour, :minute, :second, :days, :active

Have a look at http://www.rubycentral.com/pickaxe/tut_classes.html

hth
alex

Thanks Alex, I’ll look into that and see if I can’t figure it out. As
you can see I’m still a bit new to everything, so thanks again for your
trouble.