-
Content Count
286 -
Joined
-
Last visited
-
Days Won
2
Posts posted by Yaron
-
-
I am using the microsoft's WebView2 API to embed the chromium based edge browser inside my Delphi 7 application (using Winsoft's WebView2 wrapper component).
My problem is that WebView2's ExecuteScript function returns results asynchronously through a call-back function, which is a problem because my app needs to setup a few things based on the javascript function's result and can't proceed until the data is available.
I couldn't find any way in Delphi to process the results synchronously without calling "Application.ProcessMessages" in a loop until the result function is triggered (I can't use "Sleep" because then the result function will never be triggered).
Of course calling "Application.ProcessMessages" in a loop is not very desirable, so I'm wondering if there's a better approach?
-
5 hours ago, Fr0sT.Brutal said:How a browser component could be non-valid? They must be limiting all browsers then which doesn't happen obviously. Maybe server expects some headers to distinguish standalone browser from an embedded component, try to mimic them
Sorry if I wasn't clear, I was referring to DirectShow which does not use a browser component. It does use http transport and you can specify the user-agent, but it makes no difference, somehow YouTube identifies it and limits the bandwidth to unusable levels.
-
On 10/26/2021 at 10:44 AM, Fr0sT.Brutal said:Hmm, https://www.ffmpeg.org/index.html#news seems pretty fresh and it's used by youtube-dl for decoding YT videos so it should work.
From what I can tell, the problem is that YouTube is now detecting non-valid clients and then putting a bandwidth limiter on the connection, making playback unpractical.
At least that's I experience when trying to use the D3YD YouTube Directshow filter.
On 10/21/2021 at 12:11 AM, Kevin Koehne said:We use this component with D2007. It appears to support most versions of Delphi.
I am experimenting with it now, I can get it to load the video, but I'm still not sure how to capture javascript event and send the event's data back to Delphi.
-
On 10/21/2021 at 10:37 AM, Fr0sT.Brutal said:I have no idea about legality and pretty sure you considered that but doesn't playback via ffdshow solve the problem?
If you mean using DirectShow, there was a filter for that, but it's no longer functioning correctly after youtube changed something server-side and the developer is no longer responsive.
-
4 hours ago, Fr0sT.Brutal said:This sounds weird to me.
@Fr0sT.Brutal It's the H.264 codec and AAC audio, it's sort of gray legally, but I'd rather avoid any such hassle.
Probably around $200. It's basically a wrap-up job with minimal logic (I'm doing the YouTube/javascript code, I just need access to the component/events and bridge to javascript commands/events.
-
This is a tough one, I need advice.
I currently offer the option to play YouTube video content in my Delphi 7 app by using YouTube's IFRAME player and Javascript API inside a TWebBrowser component.
Unfortunately, the TWebBrowser component is limited to the Edge Legacy engine (Edge v11) and is dropping frames like crazy, which is why I would like to move the code to use the Edge Chromium engine.
Previously, Microsoft let you choose the engine by specifying a registry key (HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION), but it seems that with the Chromium version, they dumped the old IWebBrowser interface for a new WebView2 interface.
Unfortunately, I haven't found any WebView2 support for Delphi 7. It seems WebView2 support was only introduced in Delphi 10.4 and I only own Delphi 10.3 and can't afford paying $1000+ just for this feature.
I'm aware of Delphi Chromium Embeded 3 project, but it may have legal issues with the decoders required to play YouTube content, so it's not an option.
So the questions are:
- Can I hire someone to write a DLL I can then use in Delphi 7, giving me the functionality I need (video position within my window handle and a Javascript bridge to the YouTube API data/events)?
- Is there a WebView2 implementation that I missed and is compatible with Delphi 7 or at least would allow me to generate a DLL I can use in Delphi 7, but write in Delphi 10.3?
- Is there an option I haven't considered?
-
@Kas Ob.I wasn't intending for my app to do the mixing, windows does it itself automatically as long as the audio device is not locked exclusively.
I'm not sure if your solution is per-application or affects the entire system. I guess I have to do some more research.
-
@Kas Ob. Passing a volume level greater than 100 does digital amplification? If that's the case then it's a non-issue as I don't plan on allowing greater than 100 volume.
-
Thank you, I really appreciate your effort and time, I will try it out shortly.
How does the rare mixer timing bug manifest itself, what should I be looking for?
-
There are currently 5 events that trigger a different .wav file playback, might be extended to 9 in the future.
With regards to output devices, I mean on my PC I have speakers and a TV set, with DirectShow I can control whether the audio is played through the speakers or through the TV set.
-
VCP looks like a massive library, I looked at the waveplayer demo and it doesn't seem to support output device selection.
If you have experience with VCP, can you give me a few pointers, my goal is play .wav files asynchronously in the background as the user is traversing the menu.
I currently use this function structure "PlaySound(sAudio : WideString; sDevice : String; iVolumeLevel : Integer);"
Where sAudio is the ".wav" filename, sDevice is the audio device name and iVolumeLevel is a volume value from 0 - 100.
-
-
-
Delphi 7, Windows 10.
I wrote a menu system that plays SoundFX (basically WAV files) based on user actions.
I need to be able to control the playback device, volume and support asynchronous concurrent playback of multiple SFX.
To do this, I decided to go with DirectShow and it worked like a charm. However, each time you play an audio through DirectShow it creates multiple threads which are then terminated as the DirectShow graph is stopped.
So even if you play a single SFX, each time the SFX is triggered, Directshow will create and destroy several threads in the process.
I believe this behavior is contributing to memory fragmentation in my app.
Is there a method other than DirectShow to asynchronously play WAV files with volume control and allowing audio device selection for output?
-
I'm using Delphi 7, 16GB ram, Windows 10.
I needed to write a SoundFX playback module that supported multiple audio devices, volume level, and multiple effects playing.
I thought the smartest/cleanest way would be to create a new thread for each SFX, play it using DirectShow and then let the thread clean itself up.
It seemed like an elegant solution, just fire and forget, windows took care of the sound mixing and it worked reasonably well.
That is, until my GDI+ based JPEG decoding code started exhibiting random memory allocation issues.
I'm not too familiar with underlying windows memory management, but it seems that there is memory defrag operation that works in the background, otherwise the memory allocation issues would be constant and not random (working, not working and working again in the span of a second).
Is there a WinAPI function I can call to defrag my app's memory?
In the meanwhile I'm trying to work around this issue by reusing threads instead of going through many create/destroy cycles, but I'm still interested if there's an answer to my defrag question.
-
1 minute ago, luebbe said:The grijjy timer queue works fine. I'm using it to draw on screen in regular intervals. You shouldn't allow VCL style changes while drawing, It got me into all kinds of trouble.
The code I'm calling is very thread-unsafe, I would have to completely rewrite several sub-systems to make it thread safe, I think it would be more beneficial if I could somehow instantly synchronize the code.
Thing is, how does synchronize work, is it only triggered on a system tick? If so, I'm stuck at again at the 16ms tick timing and this whole approach is pointless unless I rewrite a lot of code.
I discovered a few things regarding timeBeginPeriod :
1. From MSDN: "Prior to Windows 10, version 2004, this function affects a global Windows setting. For all processes Windows uses the lowest value (that is, highest resolution) requested by any process. Starting with Windows 10, version 2004, this function no longer affects global timer resolution. For processes which call this function, Windows uses the lowest value (that is, highest resolution) requested by any process. For processes which have not called this function, Windows does not guarantee a higher resolution than the default system resolution."2. timeBeginPeriod doesn't work as advertised. If i use timeBeginPeriod(16), you'll get the usual 16ms timer accuracy, however, at least on my system (fully patched win10), calling timeBeginPeriod(15) is enough to set an actual timer accuracy of 1-2ms.
So if I can't find a way to synchronize callbacks without changing periodic timer accuracy, I believe using timeBeginPeriod with tthread/Sleep/synchronize is the safest approach I can use.
-
According to the GitHub sample I linked above, "The stdcall [callback] procedure will be called for each interval for each and every timer in the queue. In other words, you can expect this event to be called by multiple threads and it needs to be completely thread safe".
So this brings up my previous question, how can I synchronize the actions I want to take with the main thread?, otherwise my code will not be thread safe.
-
7 minutes ago, FPiette said:I don't know what you draw on screen, but have you considered off-loading everything to the GPU? Much like a game.
I can't use the GPU, it would mean rewriting A LOT of code and in my use-case I actually prefer the GPU to be free to do other things.
Does anyone know if the callback function in CreateTimerQueueTimer runs within my app's main process thread or in a completely different thread?
If it's in a different thread, how do I synchronize the call to make sure it's running in the main thread? Using critical sections or is there another mechanism I'm not thinking of?
-
Just now, Anders Melander said:Yes, I understood that but if you're concerned about not wasting resources, as you state, then there's no reason to refresh more often than what the monitor can handle.
I don't care about wasting resources while there's screen updates to generate, I'm concerned about wasting resources when doing nothing but waiting for the next update.
Trying to work with v-sync is a pain, if you miss an update window there's serious judder.
-
I found a good resource at https://github.com/grijjy/DelphiTimerQueue
Hopefully it will resolve my issue, the workaround I'm currently using is having multiple thread that keep trying to update the screen if at least 1ms passed since another thread triggered an update. Not really the best approach.
-
1 minute ago, Anders Melander said:Okay, that makes better sense.
Instead of updating at a fixed 120 Hz I think you'll want to sync your refresh to the monitors vertical retrace. I don't know how to do that but I found this: http://masm32.com/board/index.php?topic=4410.0
I don't want to block for v-sync, I don't care if there's tearing. I just want to get 60+fps screen updates without bogging down a CPU core.
I'm looking at queue timers as FPiette mentioned (looks like multimedia timers were depreciated in favor of queue timers), if anyone has a sample using "CreateTimerQueueTimer" in Delphi (compatible with Delphi7), that would be cool.
-
Just now, Anders Melander said:If a regular WM_PAINT handler will not update fast enough I can't see how a timer controlled paint will. What am I missing?
The problem is not the frame-update speed (which on my PC is about 3ms), it's about how to time the call to update the screen within a specific time-frame and not in 16/32ms intervals.
-
I want smooth scrolling, using Sleep(1), I measure 15-30ms delay per frame, resulting in unstable scrolling because the delay between screen-updates is inconsistent/juddery and ~33fps which looks really bad.
-
I have a function I'd like to call 120 times per seconds using TThread.Synchronize (as the function updates the screen).
I don't want to completely bog down a CPU core by constantly calling "QueryPerformanceFrequency" in a loop until the time is right to trigger the function.
I originally envisioned using Sleep(1), but in reality, Sleep(1) usually means 15.6ms unless I change the entire system's Tick accuracy using "TimeBeginPeriod/TimeEndPeriod".
However, I don't want to affect the entire system as I've read there's a harsh 25% battery impact when switching the accuracy and I don't want to drain the client's battery.
So what is the best, most precise way to time/trigger synchronized calls from a thread?
WebView2 synchronious calls
in Windows API
Posted
I'm not sure how event driven would help me here, I have to wait until specific data is returned from a javascript function before allowing the code to proceed.
Here's a real life example:
1. A user presses "play" in my app to play content.
2. I execute a javascript function to return data on the content (e.g. duration in seconds).
3. I now need to display the a position bar on a timeline to the user, which uses a combination of duration and the current position (which isn't always "0" when starting playback of live feeds).
As soon as the user presses "play", I want to block all UI interaction until I get my data back from the javascript function.
Sure, I can artificially block UI interaction by disabling every UI entry point, but that would be a messy workaround when all I need is the javascript function to return the result synchronously.