How to properly use mciSendString - delphi

I play an MP3 sound using the following mciSendString
mciSendString("play \"mysound.mp3\"", NULL, 0, 0);
The above works just fine. But from what I've seen around the web, people use all kinds of wrappers for the above code. Some first send open command then play, then wait for notification, then send close command, they also use aliases for files etc.
My question is - is all this necessary? My primary interest is just to play a file and do it in async manner. The above command appears to do all the cleanup so my question is - is it really required to use open or close command and notifications when the sound has been played to properly release memory and deallocate sound and is there an advantage to doing so.
From what I can see in the debugger it appears that on execution of above command the system loads required DLLs, then starts some threads and as soon as the playback ends, the threads exit and the DLLs are unloaded. So my guess is that open/close are optional because the system does all the allocation/deallocation automatically, but I may be wrong. Am I leaking some memory or resources if I just call the above line and nothing else?
Here is what the debug log shows - all I can conclude from this log that the thread is closed and that the the DLL files are unloaded:
Module Load: MCIQTZ32.dll. No Debug Info. Base Address: $61D80000. Process Project1.exe (368)
Thread Start: Thread ID: 492. Process Project1.exe (368)
Module Load: SETUPAPI.dll. No Debug Info. Base Address: $77920000. Process Project1.exe (368)
Module Unload: SETUPAPI.dll. Process Project1.exe (368)
Thread Start: Thread ID: 1344. Process Project1.exe (368)
Thread Start: Thread ID: 640. Process Project1.exe (368)
Thread Exit: Thread ID: 1344. Process Project1.exe (368)
Thread Exit: Thread ID: 640. Process Project1.exe (368)
Thread Start: Thread ID: 468. Process Project1.exe (368)
Thread Start: Thread ID: 1120. Process Project1.exe (368)
Module Load: SETUPAPI.dll. No Debug Info. Base Address: $77920000. Process Project1.exe (368)
Module Unload: SETUPAPI.dll. Process Project1.exe (368)
Thread Start: Thread ID: 1692. Process Project1.exe (368)
Thread Start: Thread ID: 1384. Process Project1.exe (368)
Thread Start: Thread ID: 204. Process Project1.exe (368)
Thread Start: Thread ID: 1572. Process Project1.exe (368)
Thread Exit: Thread ID: 1692. Process Project1.exe (368)
Thread Exit: Thread ID: 1384. Process Project1.exe (368)
Thread Exit: Thread ID: 1572. Process Project1.exe (368)
Thread Exit: Thread ID: 204. Process Project1.exe (368)
Thread Exit: Thread ID: 1120. Process Project1.exe (368)
Thread Exit: Thread ID: 468. Process Project1.exe (368)
Module Unload: MCIQTZ32.dll. Process Project1.exe (368)
Thread Exit: Thread ID: 492. Process Project1.exe (368)

I found the answer elsewhere so I'm sharing it.
It appears that the play command by itself is perfectly valid.
So here are a couple of ways to call this:
// (a)
mciSendString("open waveaudio!MyFile.wav alias MyFile",NULL,0,0);
mciSendString("play MyFile wait",NULL,0,0);
mciSendString("close MyFile",NULL,0,0);
// (b)
mciSendString("open MyFile.wav alias MyFile",NULL,0,0);
mciSendString("play MyFile wait",NULL,0,0);
mciSendString("close MyFile",NULL,0,0);
// (c)
mciSendString("play MyFile.wav wait",NULL,0,0); // no open or alias used
Answer found on MSDN Forums.
Once important thing worth noting is thatmciSendString will fail miserably if you supply it with filename with spaces in the path (e.g. C:\Program Files...). Even if you enclose this into quotes it won't help. The solution is to use GetShortPathName Windows function to get a DOS-like path from NTFS path name and which doesn't have spaces in it.

Related

Nativescript app works on simulator but not on real device. Crash report says EXC_BAD_ACCESS (SIGSEGV)

I have a Nativescript-Angular mobile app. It works on simulator well. But once it's published to Apple store, it works on older model like iphone 7, but not on iphone 10/11/12. The ios version are all 14+ so I don't think that's the cause.
I pulled the crash report from my phone, it just has some error messages like these. Could anyone give me some ideas or point me in the right direction of how to research on this?
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000000280b350
VM Region Info: 0x280b350 is not in any region. Bytes before following region: 4324461744
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 10442c000-104430000 [ 16K] r-x/r-x SM=COW ...e.app/LBELite
Termination Signal: Segmentation fault: 11
Termination Reason: Namespace SIGNAL, Code 0xb
Terminating Process: exc handler [508]
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x000000019ffbc658 0x19ffb7000 + 22104
1 libobjc.A.dylib 0x000000019ffbcf88 0x19ffb7000 + 24456
2 NativeScript 0x0000000104da4930 0x104d30000 + 477488
...
Thread 1 name: JavaScriptCore bmalloc scavenger
Thread 1:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 2:
0 libsystem_pthread.dylib 0x00000001d6a58764 0x1d6a4e000 + 42852
...
Thread 3 name: Heap Helper Thread
Thread 3:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 4 name: Heap Helper Thread
Thread 4:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 5 name: Heap Helper Thread
Thread 5:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 6 name: Heap Helper Thread
Thread 6:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 7 name: Heap Helper Thread
Thread 7:
0 libsystem_kernel.dylib 0x00000001b8ef41ac 0x1b8ecc000 + 164268
...
Thread 0 crashed with ARM Thread State (64-bit):
x0: 0x000000000280b348 x1: 0x0000000280b34b60 x2: 0x0000000000000000 x3: 0x0000000000000034
...
esr: 0x92000006 (Data Abort) byte read Translation fault
The runtime library you are using, NativeScript is supplying a much too low valued data pointer to the objective-C runtime. When this memory location, 0x000000000280b350, is accessed, the Kernel notices there is no Virtual Memory mapped for that address, giving a Data Abort. Your esr register has top bits binary 100100. The ARM manual says
Used for MMU faults generated by data accesses, alignment faults other than those caused by Stack Pointer misalignment, and synchronous External aborts, including synchronous parity or ECC errors. Not used for debug-related exceptions.
A common reason for low-valued data addresses is that there has been code that offsets a value from some other base value, and the thing the gets the base value returned nil, or gave you 0. Your bad value is kind of large for such a problem (normally you'd see a bad value like 0x230 or something).
The reason I think your code is breaking is that the underlying library must have an architecture-specific aspect of code to it. It is likely that the code supports Intel (assume you are using an Intel based Mac), and older ARM chips but not the newer chips. iPhone X is using the A11 Bionic chip.
Are there any other apps you have that use this technology stack but work on the latest hardware? Do you have an iPhone X, does that work locally? Is there any updated versions of your NativeScript support you can try?
There is a small chance that the foul-up is due to the App Store re-compiling your BitCode before sending it to the customer, and that has introduced a fault. Is BitCode enabled in your build archive?
What version of the IOS runtime are you using? I was having similar issues until I updated from 6.5.0 to 6.5.4.

MobileVLCKit player shows black screen on iOS 11

In my project using MobileVLCKit 3.0.0 for playing media.
All types of videos successfully playing on iOS9&10 but on iOS 11 video audio able to listen but the picture doesn't display and shows the black screen.
Gives below logs:
2017-09-18 18:26:17.640065+0800 DemoPlayer[39923:369260] creating player instance using shared library
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView bounds]
PID: 39923, TID: 369593, Thread name: (none), Queue name: com.apple.root.default-qos.overcommit, QoS: 21
Backtrace:
4 DemoPlayer 0x0000000108349895 Open + 405
2017-09-18 18:26:23.490963+0800 DemoPlayer[39923:369593] [reports] Main Thread Checker: UI API called on a background thread: -[UIView bounds]
PID: 39923, TID: 369593, Thread name: (none), Queue name: com.apple.root.default-qos.overcommit, QoS: 21
Backtrace:
4 DemoPlayer 0x0000000108349895 Open + 405
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIView initWithFrame:]
PID: 39923, TID: 369593, Thread name: (none), Queue name: com.apple.root.default-qos.overcommit, QoS: 21
Backtrace:
4 DemoPlayer 0x0000000108349f3b -[VLCOpenGLES2VideoView initWithFrame:zeroCopy:voutDisplay:] + 91
2017-09-18 18:26:23.875359+0800 DemoPlayer[39923:369593] [reports] Main Thread Checker: UI API called on a background thread: -[UIView initWithFrame:]
PID: 39923, TID: 369593, Thread name: (none), Queue name: com.apple.root.default-qos.overcommit, QoS: 21
Backtrace:
4 DemoPlayer 0x0000000108349f3b -[VLCOpenGLES2VideoView initWithFrame:zeroCopy:voutDisplay:] + 91
2017-09-18 18:26:23.959355+0800 DemoPlayer[39923:369593] CoreAnimation: [EAGLContext renderbufferStorage:fromDrawable:] was called from a non-main thread in an implicit transaction! Note that this may be unsafe without an explicit CATransaction or a call to [CATransaction flush].
shader program 1: WARNING: Output of vertex shader 'TexCoord1' not read by fragment shader
WARNING: Output of vertex shader 'TexCoord2' not read by fragment shader
thanks in advance.
Finally, got the solution...
Now 'MobileVLCKit-Unstable' version updated into master on Sep 20 with UIKit from a background thread(iOS 11 Video play) issue.
Solution1:
Add pod 'MobileVLCKit-unstable', '3.0.0a38' to podfile and run pod install
Solution 2:
Cloned the repo from the following URL: http://code.videolan.org/videolan/VLCKit.git
Open terminal, navigate to root directory and execute ./buildMobileVLCKit.sh -f (Note: It may take 1-2 hours to complete)
On successful completion, the MobileVLCKit.framework will be generated in VLCKit/build/ folder location.
Simply drag it to your project.
You need to update MobileVLCKit to the pod 'MobileVLCKit-unstable' in version '3.0.0a38' or later. This problem was resolved. There is no way to make older releases of the library work in any way as it calls to UIKit from a background thread.

Delphi Monitoring Existing Processes

I'm new to this so sorry in case my question seems to be silly, I'm writing a Delphi program in which I'm running a list of external executables though multiple threads in a queue and waiting for them to finish using CreateProcess like:
CreateProcess(Pchar(NotepadExe), Nil, Nil, Nil,
False, NORMAL_PRIORITY_CLASS,
Nil, Nil, StartupInfo,ProcessInfo),
and
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
now the programs I called are performing lengthy jobs, so in case my program got closed while the external executables are still running, is there an easy way to regain access to the processes and waiting for them again? and what about the case when some of them are finished already?
I did sort of what #SertacAkyuz suggested, and it works
During execution I add the current process id to a file using
GetCurrentProcessId
When I start my program I read from the file the saved processIds then determine which of the currently running processes are children which I already ran, afterwards I create a thread to open and monitor the same again
uses tlhelp32;
----
var Snap:THandle;
ProcessE:TProcessEntry32;
----
Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
ProcessE.dwSize:=SizeOf(ProcessE);
if Process32First(Snap,ProcessE) then
begin \\Iterate through running processes
while Process32Next(Snap,ProcessE) do
\\Determine whether it's a child process of the saved PiD
if ProcessE.th32ParentProcessID = mySavedPiD then
\\ Creating the thread to monitor the process
cnThread:=TContinueThread.Create(ProcessE.th32ProcessID);
cnThread.Start;
\\ In the thread Execute
var hndl:THandle;
----
hndl:=OpenProcess(PROCESS_ALL_ACCESS ,False,PiD);
WaitForSingleObject(hndl, INFINITE);
It might not be the best solution but it works for me for now, however, still I need to handle the delta (processes which got finished during my program absence)
Creating a thread for each started process, wastes a thread. And the internal thread resources are limited. If you're using WaitForSingleObject(,INFINITE) now, take the time to learn about WaitForMultipleObjects and start a single thread to wait on a number of processes. (Or learn about jobs like #DavidHeffernan proposes)

What's the difference between TIdNotify and TIdSync?

I'm in trouble understanding the real difference between IDSYNC and IDNOTIFY, what means synchronous / asynchronous
in respect to the lines of code I write ?
procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
begin
....
DoSomeThing (TIDNotify) ....
DoSomethingOther(TIDsync) ......
end;
Why can't I be sure that both lines of code are executed within the TCPServer Execute function?
Is there only the risk that a few lines of code are not executed within my TIDSynfunction or how can a Deadloack be explained ?
TIdSync and TIdNotify accomplish the same goal - to execute a piece of code in the context of the main thread - but they do it in different ways.
TIdSync is synchronous. The TIdSync.Synchronize() method blocks the calling thread until after the main thread has called the TIdSync.DoSynchronize() method and it has exited. A deadlock can occur if TIdSync.Synchronize() is called within a server event handler while the main thread is shutting down that server. This is because the main thread is blocked waiting for the server to terminate its threads. But the thread is blocked waiting for the main thread to process the sync request.
TIdNotify is asynchronous. The TIdNotify.Notify() method adds the TIdNotify.DoNotify() method into a background queue and exits immediately, so the calling thread is not blocked. The main thread calls the TIdNotify.DoNotify() method at its leisure. There is no deadlock in this situation.

topic regarding POSIX thread

How does a thread knows when to exit?
SITUATION:
-while the main program must wait for the threads to run to completion.
-This can be done by using a prototype function called pthread_join.
-after all, a call to this function waits for the termination of the thread whose id is given by thread itself.
After you have called pthread_join(ptherad_t &var)the main will wait untill all the threads for which you have called join have exited.
once all the threads are completed their tasks,
when it calls pthread_exit(NULL) main will exit.
inside the thread after its task is completed you need to call pthread_exit(NULL) which will stop the excution of the thread.But this is not mandatory and the thread can simply return which means that the thread has completed.
when it(thread) calls pthread_exit(NULL),the calling thread will exit.

Resources