connect Shoes.app to signals from external class
- From:
- J. Kaiden
- Date:
- 2011-06-02 @ 11:18
hi folks,
i've got a question about making a Shoes.app aware of signals from an
external class. below is a dumb example for simplicity's sake, but what i'm
really trying to do is connect to gstreamer's EOS (end of song) signal
emitted by an external player class instantiated in my Shoes.app, in order
to update the Shoes GUI as the songs change.
gstreamer watches a bus for signals, and emits them when they are found -
which i've tried to emulate here using the #.times method, though i'm not
sure it's a very good reproduction of what really happens, and maybe that's
where the trouble lies. i initially wrote this example using a
GLib::Timeout, but that might well only work on my build (!) so i figured
i'd try this:
#######
class DumbExample
attr_reader :signal, :shot
def initialize
@hits = [1, 3, 5, 7, 9]
end
def shoot
50.times{|time|
@signal = "nada"
@shot = rand(10)
if @hits.include?(@shot)
self.gotOne(@shot, time)
end
p "##{time} :: signal = #{@signal}"
}
end
def gotOne(shot, time)
p "##{time} :: #{shot}"
@signal = "got one"
end
end
Shoes.app do
dumb = DumbExample.new
dumb.shoot
case dumb.signal
when "got one"
para dumb.shot
end
end
##########
i run this in scite, so i can watch the output from DumbExample - and what
i notice is that the Shoes.app only responds to dumb.signal the last "time"
(#49). if i've "got one" the 49th time, i'll see it (and only it) in my
Shoes.app - otherwise i get nothing (and not "nada" ;) )
is there a way to make the Shoes.app aware of and respond to signals as
they are emitted in an external class? maybe throw a "yield" into
DumbExample#shoot, and put the case statement within dumb.shoot's block? or
am i (as is quite likely) missing something obvious?
thanks,
- j
Re: [shoes] connect Shoes.app to signals from external class
- From:
- ashbb
- Date:
- 2011-06-02 @ 12:48
Hi Jake,
> maybe throw a "yield" into DumbExample#shoot, and put the case statement
within
> dumb.shoot's block?
Yeah, try out the following. :)
##############
class DumbExample < Shoes::Widget
attr_reader :signal, :shot
def initialize
@hits = [1, 3, 5, 7, 9]
end
def shoot
50.times{|time|
@signal = "nada"
@shot = rand(10)
if @hits.include?(@shot)
self.gotOne(@shot, time)
yield
end
para "##{time} :: signal = #{@signal}\n"
}
end
def gotOne(shot, time)
para "##{time} :: #{shot}\n"
@signal = "got one"
end
end
Shoes.app do
de = dumb_example
de.shoot do
case de.signal
when "got one"
para de.shot, "\n", stroke: red
end
end
end
##############
ashbb
Re: [shoes] connect Shoes.app to signals from external class
- From:
- ashbb
- Date:
- 2011-06-02 @ 12:55
Hi again,
If you don't have to use `para` within DumbExample class. You don't have to
use Shoes::Widget like this:
class DumbExample
attr_reader :signal, :shot
def initialize
@hits = [1, 3, 5, 7, 9]
end
def shoot
50.times{|time|
@signal = "nada"
@shot = rand(10)
if @hits.include?(@shot)
self.gotOne(@shot, time)
yield
end
#para "##{time} :: signal = #{@signal}\n"
}
end
def gotOne(shot, time)
#para "##{time} :: #{shot}\n"
@signal = "got one"
end
end
Shoes.app do
de = DumbExample.new
de.shoot do
case de.signal
when "got one"
para de.shot, "\n", stroke: red
end
end
end
--------
ashbb
Re: [shoes] connect Shoes.app to signals from external class
- From:
- J. Kaiden
- Date:
- 2011-06-02 @ 21:36
you guys rule...
steve - thanks for the link - looks very interesting, checking it out
now... this could be the perfect solution. i'll let you know if i can
shoesify it...
ashbb - works like a charm... i had fooled around some with the
Shoes::Widget, and it seemed like a way to go - but as you noted, i don't
need to call #shoot within DumbExample. your second suggestion gives me
just what i was looking for.
thanks again for the ideas, rock on...
- j
Re: [shoes] connect Shoes.app to signals from external class
- From:
- J. Kaiden
- Date:
- 2011-06-03 @ 00:01
hey folks,
fooled around with the observer pattern for a bit, and came up with this,
which seems like a nice way of handling signals too:
###
require "observer"
class Publisher
include Observable
def initialize
@hits = [1, 3, 5, 7, 9]
end
def shoot
50.times{|t|
@shot = rand(10)
if @hits.include?(@shot)
changed
notify_observers(t, @shot)
end
}
end
end
Shoes.app do
def update(t, shot)
para "##{t} => #{shot}: "
end
pub = Publisher.new
pub.add_observer(self)
pub.shoot
end
###
- thanks again,
- j
Re: [shoes] connect Shoes.app to signals from external class
- From:
- Steve Klabnik
- Date:
- 2011-06-03 @ 13:02
That's awesome, I'm glad that works.
I think that Observers will end up being an important part of writing medium
to large Shoes apps.
Re: [shoes] connect Shoes.app to signals from external class
- From:
- ashbb
- Date:
- 2011-06-03 @ 11:15
Cool!
ashbb
Re: [shoes] connect Shoes.app to signals from external class
- From:
- Steve Klabnik
- Date:
- 2011-06-02 @ 12:18
Well, yes. You're not 'sending' anything, you're calling a method, then
doing the para after.
What you want is the Observer pattern:
http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html
I don't know of anyone that's used this with Shoes yet, though, so it
could be interesting!