Inserting a delay between screen updates using Val and GTK3 - vala

I am learning Vala and GTK3 in a Linux (Ubuntu 12.04) environment. To do so, I have written a Game of Life simulation. So far so good. What I would like to do is insert a delay (say 2 seconds) between each screen update. I have investigated the Glib.TimeoutSource function and it seems over-elaborate for my needs. Are there other options? If TimeoutSource is indeed the way to go, are there any examples you might recommend.
Thank you.
Mike
Update: It turns out to be ridiculously easy ...
public void onRunButtonClicked(Button source)
{
Timeout.add_seconds(3, updateDraw);
}
private bool updateDraw()
{
game.determineBirthsAndDeaths();
game.applyBirthsAndDeaths();
queue_draw();
iterationsLabel.set_text("Iteration: %5d".printf(game.getIterationCount()));
return true;
}
The first method sets the timer. The second one executes every three seconds (in this example). Now I have to add a stop button and get my updateDraw method to return false when the stop button is pressed. More to learn ...

public void onRunButtonClicked(Button source)
{
Timeout.add_seconds(3, updateDraw);
}
private bool updateDraw()
{
game.determineBirthsAndDeaths();
game.applyBirthsAndDeaths();
queue_draw();
iterationsLabel.set_text("Iteration: %5d".printf(game.getIterationCount()));
return true;
}

Related

How to verify state change in Compose?

Say in a composable I have two states:
var stateA by remember { mutableStateOf(varA) }
var stateB by remember { mutableStateOf(varB) }
varA and varB are class variables of type Int and are set elsewhere in the code.
Then somewhere in the composable, in the same scope, I have
processA(stateA)
processB(stateB)
processA and processB are not composable functions.
So after initial rendering, if neither state changes, then nothing is further processed, that is cool.
Then if say stateB is changed, then both process statements get called. But I hope only to call processB in the case and not processA. How can I detect which of the states has changed?
You should not run heavy processing directly from Composable functions. More information can be found in side effects documentation.
In this case, you can use LaunchedEffect. Using snapshotFlow, you can create a flow that emits values every time a state changes, so you can process it. You can have a flow for each state, so they will be processed independently.
LaunchedEffect(Unit) {
launch {
snapshotFlow { stateA }
.collect(::processA)
}
launch {
snapshotFlow { stateB }
.collect(::processB)
}
}

Return/break out of infinite foreach in kotlin

For class I have to make a program that calculates the birthday problem
Now I'm having trying to learn kotlin at the same time and I'm having trouble with a little snippet of code:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
outForeach#
sum += checkSet.size
As you can see I'm trying to do this with an infinite sequence. Kotlin doesn't accept this as outForeach is an unresolved reference. But this doesn't work either:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#forEach
}
}
sum += checkSet.size
This will just start the forEach loop again. Is there a way to implement something as a forEachUntil or so?
p.s. I'm aware that this looks a lot like this question: 'return' doesn't jump out of forEach in Kotlin It's just that I don't really get the answers and I don't know if its applicable here. Also a way to implement forEachUntil seems for me to be far more elegant
Alternatives you may want to consider instead of first:
using a simple while without body:
while (checkSet.add(Random.nextInt(n))); // <- that semicolon is required! otherwise you execute what is coming next within the while
using run with a label:
run outForeach#{
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
}
maybe also takeWhile might be helpful. In this specific case however it is surely not (as it would check against the checkSet and leave us with a sequence that isn't consumed... but if the condition would be different, it may make sense to consider something like take, takeWhile, takeLast, etc.):
generateSequence { Random.nextInt(n) }
.takeWhile(checkSet::add) // as said: for this specific condition it doesn't make sense...
.forEach { /* do nothing except consume the sequence */ } // the same values you added to the set would be available in this step of course
I think I found the solution myself:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.first { !checkSet.add(it) }
sum += checkSet.size
Basically use the function first() and keep returning false until you want to get out of the loop. And just drop the return of the function first()

If variable is not set, wait for variable to be set

I have 2 delegate methods that are being called by notifications from a 3rd party library.
Method 1:
mediaContentWasUpdated()
Method 2:
adMediaDidBeginPlaying()
In Method 1, a key variable (adDuration) is set from a parameter that is passed in with the notification. As far as I can see this is the only place to get this information.
In Method 2, we check the adDuration and if it is greater than 0 then we update the UI to reflect that we are in fact play an ad.
A bug has appeared where sometimes these two methods are called in the wrong order. Meaning the adDuration is not set and Method 2 thinks there is no ad media to be played and does not update the UI accordingly.
My current attempt at a solution is to make adDuration optional and use an NSCondition to cause Method 2 to wait for Method 1 to set adDuration and then proceed.
var adDuration : Double?
let condition = NSCondition()
func mediaContentWasUpdated(notification: NSNotificiation) {
condition.lock()
if(notificationHasAdDurationInfo(notification)) {
self.adDuration = getAdDuration(notification)
condition.signal()
}
condition.unlock()
}
func adMediaDidBeginPlaying(notification: NSNotification) {
condition.lock()
while adDuration == nil {
condition.wait()
}
if adDuration! > Double(0) {
updateUIForAd()
}
condition.unlock()
}
This is my first time trying something like this and I worry I am doing something wrong. I also have some concerns about locking and unlocking threads needlessly (which would happen in a well timed run, or if there were no ad content to be played).
Outside factors are hindering my ability to test and I wanted to get some input to see if I am heading in the right direction while I wait for those issues to be resolved.
Your discussion of NSCondition got me on the same track with you, and I built two or three solutions using DispatchGroup (which is the better tool for this), but they always had little corner cases that could behave badly, and didn't really capture the intent.
(If you're interested in the DispatchGroup solutions, they're of the form: call .enter() in init, call .leave() when the duration comes in, call notify() when the playing starts. It works fine, but it introduces corner cases that can crash, just like NSCondition.)
Getting back to the real intent:
Update the UI when the duration is known and the ad has started playing.
There's no concurrency going on here. So pulling out GCD is not just overkill; it actually makes things worse because it introduces lots of complicated corner cases.
So I thought about how I'd have solved this back before GCD. And the answer is obvious: just check if you have the data you want, and then do the thing. (Reading through the comments, I see Paulw11 pointed this out as well.)
Personally I like to pull this kind of thing into its own type to make things more self-contained. I hate some of the names here, but the idea should be clear:
class AdPlayer {
private var readyToPlay = false
private var duration: Double = 0.0
private let completion: (Double) -> Void
func setDuration(from notification: Notification) {
if(notificationHasAdDurationInfo(notification)) {
duration = getAdDuration(notification)
}
playIfReady()
}
func play() {
readyToPlay = true
playIfReady()
}
private func playIfReady() {
if duration > 0 && readyToPlay {
completion(duration)
}
}
init(completion: #escaping (Double) -> Void) {
self.completion = completion
}
}
When you set each thing, see if you're ready to update, and if so, update. I've gotten rid of the optional as well, since I believe the intent is "0 duration is always wrong." But you could use an Optional so you could detect actually receiving a 0 from the notification.
With that, you just set up a player property:
player = AdPlayer(completion: updateUIForAd)
(Note that the above might be creating a retain loop, depending on what updateUIForAd is; you may need a [weak self] closure or the like here.)
And then update it as needed:
func mediaContentWasUpdated(notification: NSNotificiation) {
player.setDuration(from: notification)
}
func adMediaDidBeginPlaying(notification: NSNotification) {
player.play()
}
A big advantage of creating the AdPlayer type is that it's easy to reset the system when the ad is done (or if something goes wrong). Just throw away the whole object and create another one.

Swift App Architecture

I'm building out an audio tour component of an app, and I've hit a rut on organizing and calling data. I'm totally green to iOS development; coming from a Ruby/Rails background.
Class names in bold: The goal is to trigger specific information at each tour Stop. Each Stop, will be an AudioClip and play a soundbite, or it launches a Trail to guide the user to the next Stop, or it will flash a Video modal with video, etc. And at each stop, there need to be callbacks once reached. For example, if I arrive at the art museum, I would hear a clip about the Mona Lisa and then an image of the portrait would display on the phone. But all stops are not created equal, so even though the art meseum stop has an audio file to play and an image, the stop at the park may just display a walking trail with nothing else.
I have the app set up like this:
class Stop: NSObject {
func execStop() {
// do stuff
}
}
class AudioClip: Stop { }
class Trail: Stop { }
class StopImage: Stop { }
All of these tours need to be triggered in consequential order, and the next tour stop shouldn't be shown if the current stop hasn't been reached. The best way I could come up with is something like this:
// Each stop defined as its own class
class Museum: AudioClip {
override func execStop() {
playAudio(name: "AudioFile.m4a")
showImage(name: "MonaLisa.jpg")
}
}
class Park: Trail {
override func execStop() {
addRoute([Array, of, coordinates])
}
}
class Tour: NSObject {
var stops: [Int: AnyObject] = [:]
func resume() -> Void {
let active = nextAvailableStopLookup()
let currentStop = self.stops[(active as Int)] as! Stop
return currentStop.execStop()
}
}
// Individual tours, i.e. Museum, Resturant, Hike
class MuseumTour: Tour {
var TourPoints = [
1: Museum(...)
2: Park(...)
]
}
And then in the ViewController, the current Tour would be activated and based on the last stop completed, the next one would be queued.
override func viewDidLoad() {
let queueStop: Void = MuseumTour().resume()
}
The problem
This seems like a terrible way to set up an app with a lot of overhead. Each stop is a new class, and there could be upwards of 60 stops, which is 60 separate classes. The callback is the kicker - inherited-class functions (like func playAudio on AudioClip) are unavailable in the MuseumTour class. And I'm such a novice, I don't know how exactly to trigger dynamic closures.
Is there a better way of organizing and calling this type of data?
What you are doing certainly seems very silly in any language.
As far as I can tell, and to the extent that I was able to stay awake through your description, a "stop" is just a sequence of things to do (along with a pointer to another "stop"? I can't quite tell from your description). So it seems to me that a Stop is an instance of the Stop class (or, in Swift, more likely a struct) and that's all it is; there is no need for all these classes.
Your "I don't know how exactly to trigger dynamic closures" is quite telling, since an array of functions is exactly, it seems to me, what you want a "stop" to have. Maybe your first step should be to "stop" (sorry) and learn Swift, where functions are first-class citizens and so an array of them is perfectly normal.
In my very annoying app "99 Bottles", which sings "99 Bottles of Beer on the Wall", at each line of the song, we perform one or more actions, such as taking down a bottle, or removing the bottle from the screen, and we have to know what line of the song to sing. In my app, therefore, a Phrase struct consists of what to sing along with a list of actions to perform along with it:
struct Phrase {
let sound : String // name of sound file
let actions : [() -> ()] // what else to do
}
The song as a whole is thus nothing but an array of Phrase instances. We pop the first Phrase off the array, sing the sound, and call the actions functions in sequence:
let instruction = self.stages.removeAtIndex(0) // a Phrase
self.player.play(instruction.sound) // sing
for action in instruction.actions {
action() // perform the action
}
This sounds quite similar to what you are after.
(Of course, you say you are from a Ruby background; everything I just said would be equally true in Ruby. The notion of a function as a first-class citizen should come as no surprise to you.)

How do you pass statements through an addEventListener?

Iv been trying to pass arguments through an addEventListener event in actionscript such as...
target.addEventListener("pComp", rakeSoil(target));
but i get errors.
Iv tried to google but no luck :/
Thanks for replying if you do :)
The target is already passed as part of the event, either event.currentTarget or event.target will be what you want.
If you want something else passed, create a custom event. Add the property to the custom event.
Try adding an additional method as your event listener:
target.addEventListener ("pComp", targetListener);
...
private function targetListener (event:Event):void {
rakeSoil (event.currentTarget);
}
How this is what you want:
{
var target:EventDispatcher = ...;
Function rakeSoil = function (e:Event):void
{
// handle target
}
target.addEventListener("pComp", rakeSoil);
}
rakeSoil is a first class function(or closure), when event is dispatched, it will be invoked, and you can access 'target' in it.
EDIT:
Have a look at Closure (computer science)
I have always found anonymous functions to be more trouble than they are worth. I would simply follow the standard event handler code layout. It's more formal and takes a little more effort up front, but there is no ambiguity and it is far more readable when you return to it a year from now (reduces head-scratching duration):
// Target extends EventDispatcher
private var target:Target;
public function listenToTarget();
{
target = new Target();
target.addEventListener("pComp", pCompHandler);
}
private function pCompHandler(event:Event):void
{
target.rakeSoil();
}
Although, now that I look at it more closely, why are you having this object do something that Target should be capable of handling internally on its own?

Resources