Jump to content


  • Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by Yaron

  1. Yaron

    WebView2 synchronious calls

    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?
  2. I know Delphi 7 is old, but I have projects that I maintain and once I upgraded to Windows 10, compilation/running is a lot slower compared to Win 7 (on the same machine). I believe it may has something to do with the real-time virus protection (which I disabled in Win7 and is very hard to disable in Win10), but there may be other factors I'm not aware of. Does anyone have any tips to speed things up?
  3. I think this issue has to do with the integrated debugger an some form of optimization microsoft changed in Windows 10. More info from Marco. If I disable the integrated debugger then running from inside Delphi works at the same speed as if I run it externally, so I don't think that having D7 installed under the program files folder is the cause of this issue. I tried setting "delphi32.exe" in Win7 compatibility mode, but it didn't help. I even tried running externally and then connecting the debugger, but as soon as new DLLs are loaded (playing a media file using directshow), everything is the same slowness. My problem running in a VM is that I'm developing a media player and as such, it uses a lot of hardware acceleration features and running under a VM will be a headache. And a media player needs internet access for streaming and opening a Win7 machine to the internet is a bit dangerous nowadays when security patches are no longer released. Any other ideas?
  4. I got a DM with a request on how I added Android AdMob interstitial ads, here's the code: First the definition: {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)} TInterStitialAdViewListener = class(TJavaLocal, JIAdListener) private FAD: JInterstitialAd; public constructor Create(AAD: JInterstitialAd); procedure onAdClosed; cdecl; procedure onAdFailedToLoad(errorCode: Integer); cdecl; procedure onAdLeftApplication; cdecl; procedure onAdOpened; cdecl; procedure onAdLoaded; cdecl; end; {$ENDIF} [code] Then in the private section of the main form: [code] {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)} LAdViewListener : TInterStitialAdViewListener; FInterStitial : JInterstitialAd; {$ENDIF} In the form's onCreate: {$IFDEF ADMOB_FULLPAGE} FInterStitial := TJInterstitialAd.JavaClass.init(MainActivity); {$IFDEF TRACEDEBUG} FInterStitial.setAdUnitId(StringToJString('ca-app-pub-3940256099942544/1033173712')); // google test ad {$ELSE} FInterStitial.setAdUnitId(StringToJString('ca-app-pub-xxxxxxxxxxxxxxxxxxx/xxxxxxxxxxx')); // real ad code {$ENDIF} {$ENDIF} And finally: {$IF DEFINED(ANDROID) and DEFINED(ADMOB_FULLPAGE)} constructor TInterStitialAdViewListener.Create(AAD: JInterstitialAd); begin inherited Create; FAD := AAD; {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener created');{$ENDIF} end; procedure TInterStitialAdViewListener.onAdClosed; begin {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdClosed event');{$ENDIF} //MainForm.ShowModal; end; procedure TInterStitialAdViewListener.onAdFailedToLoad(errorCode: Integer); begin {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdFailedToLoad code #'+errorCode.toString);{$ENDIF} {$IFDEF TRACEDEBUG}ShowMessage('AdFailedToLoad code #'+errorCode.toString);{$ENDIF} end; procedure TInterStitialAdViewListener.onAdLeftApplication; begin {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdLeftApplication');{$ENDIF} end; procedure TInterStitialAdViewListener.onAdLoaded; begin {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdLoaded');{$ENDIF} FAD.show; end; procedure TInterStitialAdViewListener.onAdOpened; begin {$IFDEF TRACEDEBUG}AddDebugEntry('InterStitialAdViewListener AdOpened');{$ENDIF} end; procedure TMainForm.ShowInterStitialAd; var LADRequestBuilder: JAdRequest_Builder; LadRequest: JAdRequest; begin LADRequestBuilder := TJAdRequest_Builder.Create; {$IFDEF TRACEDEBUG}LADRequestBuilder.addTestDevice(MainActivity.getDeviceID);{$ENDIF} LadRequest := LADRequestBuilder.build(); LAdViewListener := TInterStitialAdViewListener.Create(FInterStitial); CallInUIThread( procedure begin FInterStitial.setAdListener(TJAdListenerAdapter.JavaClass.init (LAdViewListener)); FInterStitial.loadAd(LadRequest); end); end; {$ENDIF}
  5. I wrote a web-facing application that uses a combination of javascript/css/html for the front-end and Delphi for the back-end. I decided to create a simple Android app that would wrap the web application using a TWebBrowser control that automatically navigates to the web application's URL. The web application's requires a login and once logged in, a token is generated sever-side and then embedded into the html of subsequent server requests for future authentication. For security reasons, I do not want to store the code used to create the token within the Android app, so the easiest way for me to perform the login would be to automatically fill in the web form fields and simulate a "submit" action. Searching the web, I only found examples of how to do this using the WinAPI version of TWebBrowser, but I'm trying to write something that will work on Android and possibly iOS, any ideas?
  6. Yaron

    WebView2 synchronious calls

    @FPiette My application has over 100 keyboard macros, many dynamically created UI elements (skinned buttons) and even a TCP/IP control API (used for remote control) that can trigger events that should not be activated while a new media is in the process of loading, I can't simply disable one button, I have to disable 100's of elements and several event triggers that may execute unwanted functionality while waiting for the javascript callback event to trigger. Sure, I can do that, but it would take a lot more work than just having WebView2 return a result synchronously like TWebBrowser is able to do. @Edwin Yip I considered CEF4Delphi, but from my initial investigation, there were several show-stoppers, including the possible illegality of including audio/video codecs required by YouTube in the compiled binary, something I'm not willing to do. With regards to the 120+ MB WebView2 download, it won't be a thing in Windows 11 as WebView2 comes pre-installed on Win11. For Win10, I offer my users a quick setup option to download and install the evergreen version of WebView2 without much hassle.
  7. Yaron

    WebView2 synchronious calls

    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.
  8. 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?
  9. 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.
  10. 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. 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.
  11. 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.
  12. @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. @FPiette 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.
  13. 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?
  14. @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.
  15. @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.
  16. @Kas Ob. 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?
  17. @Kas Ob. 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.
  18. @Kas Ob. 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.
  19. 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.
  20. @Vincent Parrett I'm using the latest version of FastMM
  21. @Kas Ob. For clarity, Sound FX is ".wav" file playback and I only use GDI+ to decode JPEG files.
  22. I am trying to build a system that will handle concurrent DB requests efficiently, there's not a lot of load, but it should be able to handle more than 1 query concurrently. I am using FireBird v3.0.4 and Delphi 10.3.2 with the TFDConnection component. I am hosting the code in an ISAPI DLL that runs on IIS 7.5. Right now I'm creating the DB connection using TFDConnection in the DLL's "initialization" section. However, I noticed that even under low-load (2-3 users), I occasionally get an "[FireDAC][Phys][FB]Error reading data from the connection." exception when performing a DB query (not the same DB query, it seems pretty random). I tried to research the error and didn't find anything clear, the best I got was : https://forums.embarcadero.com/thread.jspa?threadID=245750 Which seems to indicate that I should instance a copy of TFDConnection for every query. Before I make significant code changes to test this, I would welcome any tips on the best approach to handling DB concurrency.
  23. 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?
  24. 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.
  25. 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.