wxWidgets application loop slideshow - multithreading

I have a rather simple problem which I can't seem to solve.
I would like to write a slideshow program that also plays an audio file everytime the slide has changed. This audio files vary in lengths and I do not want to program to loop through the next entry / picture till the sound has finished playing.
Currently I have implemented a loop:
void UI_BRAINWASH::PlaySound_top()
{
wxString tmppath(parent->get_currentdirect()+parent->current_db.get_card(m_index)->get_topentryaudiopath());
ISound* firstsound = this->engine->play2D(tmppath.mb_str(), false, false, true);
while(engine->isCurrentlyPlaying(tmppath.mb_str()))
{
StaticTextTop->GetParent()->Update();
//wxSleep(3);
}
m_timer->Start(1000);
}
and this loops through the entries as expected and everything is dandy...
However, I would like, to be able to abort the programm by pressing the Escape amongst other things, but the while loop obviously hinders me from doing exactly that.
I also noticed that I can't move my window or close the programm while it is looping through the pictures.
So I have looked at threads and the wxIdleevent class. in: wxwidgets/samples/threads/ is an example of a "workers thread", which seems to be what I need.
My question now is: are threads not a bit of an overkill for a simple slideshow?
Is there another / better way of looping through my entries - waiting for the sound to have played, updating the gui and also being able to still move the window around?

What is engine?
Most APIs for playing sounds provide the ability to start playing a sound-file and then return immediatly. They will send an event when the sound is finished. They will also provide a call to interrupt a sound that is still playing. This is what you want.
You should check the docs for whatever API you are using and find this feature. If the feature is not available, than you need to find another API that does - most do.

Related

How to force reimport of texture in godot?

I have a sample.png file which is being changed outside godot
and after it's modified, godot recives a signal and when that signal is received
I want that specific sample.png file to be reimported
I tried this answer but I want to reimport in my script itself not create a plugin for it
(atleast that's what I'm assuming it does)
I also tried this from the documents but I'm not sure how to use it exactly
EditorFileSystem.update_file("res://Assets/sample.png")
so how do I achieve the desired result?
The class EditorFileSystem is intended for plugins.
You would call get_editor_interface() from an EditorPlugin (which would be where you would be writing code if you were making a plugin). And that gives you an EditorInterface object, on which you can call get_resource_filesystem() which gives you an EditorFileSystem object.
So the intended use is something like this:
extends EditorPlugin
func example() -> void:
var editor_file_system := get_editor_interface().get_resource_filesystem()
editor_file_system.scan_sources()
# editor_file_system.update_file("res://icon.png")
By the way, EditorInterface also has a filesystem_changed signal. Although I don't know how reliable it is.
Usually you don't have to do that. When you restore the Godot window, it will scan for changes in the project folder. So you might minimize Godot while you are working on something else and when you bring the Godot window back it will pick on the changes.
In practice, the only situations when I had to use scan or scan_sources was when I had a tool script that write a resource file which should be imported, and I wanted it to reflect right away.
Instead of making a custom plugin, I'll remind you that form a tool script (as long as it is running in the editor) you can simply create an EditorPlugin object. For example:
var ep = EditorPlugin.new()
ep.get_editor_interface().get_resource_filesystem().scan()
ep.free()
I had also shared this example in another answer I wrote for you a while back here, it is under the title "About saving resources from tool scripts".

Getting this error "add_child: Parameter "p_child" is null" and can't seem to track it down

add_child: Parameter "p_child" is null
I suspect this is a Godot editor error because the game runs fine.
This one is hard to describe but basically I have a "memory" card game that runs from a grid. You select your difficulty and then press New Game. The first time, there are no errors but if you win or select "New Game" the errors start piling up and they seem to double each time, maxing out at 100 errors each time you press the new game button.
The only thing on the googles seems to be related to C++ (which that p_child name definitely suggests) but I'm not using C++, I'm using GDScript... this is why I'm thinking maybe it's just an editor error and Godot is just getting confused that I didn't add_child in the C++ way.
Any thoughts?
EDIT
the code generating the errors is this:
func dealDeck():
randomize()
deck.shuffle()
var c = 0
while c < deck.size():
Game.get_node('grid').add_child(deck[c])
c += 1
Game is just a reference to the main scene (/root/Memory) and deck is an array created previously that contains all the cards. I'm 99% sure that the problem isn't in the deck creation.
and to be clear, I am clearing the grid when a new game is started but I have my suspicions that something is going wrong with the whole process (even though the game is working)
Since Godot was written in C++, the errors given in the console are from the C++ side of the editor. This does not mean that your GDScript code is not responsible for the error. It seems like you're trying to add a child to an object but the child you are trying to add is null. This may be due to many reasons. You should start by looking at how you add the cards to your scene when a new game starts. Also, if you could show us some of the code we may be able to help you further.

HTML5 Audio long buffering before playing

I'm currently making an electron app that needs to play some 40Mbyte audio file from the file system, maybe it's wrong to do this but I found that the only way to play from anywhere in the file system is to convert the file to a dataurl in the background script and then transfer it using icp, after that I simply do
this.sound = new Audio(dataurl);
this.sound.preload = "metadata"
this.sound.play()
(part of a VueJS component hence the this)
I did a profling inside electron and this is what came out:
Note that actually transferring the 40Mbytes audio file doesn't take that long (around 80ms) what is extremely annoying is the "Second Task" which is probably buffering (I have no idea) which last around 950ms, this is way too long and ideally would need it under <220ms
I've already tried changing the preload option to all available options and while I'm using the native html5 audio right now I've also tried howlerjs with similar results (seemed a bit faster tho).
I would guess that loading the file directly might be faster but even after disabling security measures put by electron to block the file:/// it isn't recognized as a valid URI by XHR
Is there a faster way to load the dataurl since all the data is there it just needs to be converted to a buffer or something like that ?
Note: I can not "pre-buffer" every file in advance since there is about 200 of them it just wouldn't make sense in my opinion.
Update:
I found this post Electron - throws Not allowed to load local resource when using showOpenDialog
don't know how I missed it, so I followed step 1 and I now can load files inside electron with the custom protocol, however, nor Audio nor howlerjs is faster, it's actually slower at around 6secs from click to first sound, is it that it needs to buffer the whole file before playing ?
Update 2:
It appears that the 6sec loading time is only effective on the first instance of audio that is created. I do not know why tho. After that the use of two instances (one playing and one pre-buffering) work just fine, however even loading a file that isn't loaded is instantaneous. Seems weird that it only is the firs one.

wxpython threading textctrl disappears until files are processed

Appropriate code provided below. I had this working once but have since messed up due to having to change some of the other code. Can't figure out what I've done. The encrypt function creates a thread and makes a call to function EncryptProc to process one or more files. Once each file is completed it should print the name to a textctrl. In the codes current state it waits until all threads/files are processed before printing. It then prints evrything in one go. During processing the textctrl also completely disappears. Any help would be much appreciated as its starting to drive me nuts, lol.
---EDIT---
CODE REMOVED
There should be no GUI access from within threads - in your case EncryptProc is writing to the text control directly - you need to either:
Use CallAfter in the thread to update the text control after the thread exits or
Raise custom event an event in the thread that carries the file name information
and have a hander in the main thread that updates the text control
on receiving the event.

Jplayer 'play' command after 'pause' with time

Hello i am using jplayer for my solution. I load the media and on ready i use ('pause', time) command.
After that if i use a ('play') command my media starts playing from the beggining.
Is there something i do wrong as on jplayer's dev guide it is said on the play method:
"Open media will play from where the play-head was when previously paused using jPlayer("pause", [time])."
I encountered similar problem, when dealing with lost connection. jPlayer resumed playback from the beginning when a .play() method was called. So, at some point (in my case it was the error handler) I was executing $("#jquery_jplayer_1").jPlayer("play", event.jPlayer.status.currentTime);. It gets current position and orders jPlayer to play from that exact position. Works flawlessly for me.
But, please, provide some code, maybe your problem is completely different.

Resources