Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Programming and Hacking > Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 15th June 2019, 15:49   #1  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
implementation to force player being single instance

I've received a feature request to mpv.net to force a single instance and replace and/or queue files to the playlist.

https://github.com/stax76/mpv.net/issues/24

How would I know that an instance is already running, I've read in the past that people use a file lock for this, does that make sense and which folder would this file be located?

Which options do I have for process communication? I guess I have to pass a single string or file, if I remember right then I need FindWindow and SendMessage, I can find stuff, only need some minor clues to ensure not going in the wrong direction.

I would like to keep the code being compact, fast and simple and reliable of course.

Last edited by stax76; 15th June 2019 at 15:51.
stax76 is offline   Reply With Quote
Old 15th June 2019, 16:09   #2  |  Link
Groucho2004
 
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
Quite easy to do with the Win32 API:

Code:
::CreateMutex(NULL, TRUE, "__my__app__single__instance__lock__"); //make sure that string is unique

if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
 printf("One instance of this program is already running");
 return;
}
Should be easy to transpose to C#.

BTW, first hit on Google:https://stackoverflow.com/questions/...app-in-c-sharp
__________________
Groucho's Avisynth Stuff

Last edited by Groucho2004; 16th June 2019 at 11:06.
Groucho2004 is offline   Reply With Quote
Old 15th June 2019, 16:45   #3  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
That looks good.

Any suggestion on passing the playlist string?
stax76 is offline   Reply With Quote
Old 15th June 2019, 16:59   #4  |  Link
mariush
Registered User
 
Join Date: Dec 2008
Posts: 589
You could make your own. Create an API and have your player listen on a tcp or udp port for commands, and have the second instance send a message to listening instance then quit
There's named pipes which may not work well with .net , there's also ways in Windows to pass messages between applications

You could easily download the source code from MPC-HC and check how it's done there.

Last edited by mariush; 15th June 2019 at 17:02.
mariush is offline   Reply With Quote
Old 15th June 2019, 19:57   #5  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
I'll try window messages I guess, staxrip might do it that way, I don't remember it exactly.
stax76 is offline   Reply With Quote
Old 16th June 2019, 06:04   #6  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
Quote:
There's named pipes which may not work well with .net
Why might it not work well in .NET? Named pipes is an ordinary WinAPI for which .NET has built-in library support.

.NET has awesome WinAPI support, both built-in library and custom C/COM interop is great.

Here is a C# project that uses named pipes:

https://github.com/stax76/wox-mpv-plugin

mpv.net has a built in command palette feature so for me the wox plugin is deprecated.
stax76 is offline   Reply With Quote
Old 16th June 2019, 08:47   #7  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
I settled to do the following:

Use a mutex to figure out if there is already a instance running.
  1. use RegisterWindowMessage to register a unique window message
  2. write data to registry
  3. use SendMessage to send message to already running instance
  4. in already running instance read and remove data from registry

Last edited by stax76; 16th June 2019 at 08:51.
stax76 is offline   Reply With Quote
Old 16th June 2019, 17:37   #8  |  Link
LoRd_MuldeR
Software Developer
 
LoRd_MuldeR's Avatar
 
Join Date: Jun 2005
Location: Last House on Slunk Street
Posts: 13,248
Quote:
Originally Posted by stax76 View Post
I settled to do the following:

Use a mutex to figure out if there is already a instance running.
  1. use RegisterWindowMessage to register a unique window message
  2. write data to registry
  3. use SendMessage to send message to already running instance
  4. in already running instance read and remove data from registry
Instead of passing data in the registry, I highly recommend you pass data (messages) in a shared memory region.

This is straightforward with CreateFileMapping() – just set hFile to INVALID_HANDLE_VALUE in order to create a memory mapping not backed by a physical file – and OpenFileMapping().

See here for some details:
https://docs.microsoft.com/en-us/win...-shared-memory

I suggest you organize your shared memory as a ring-buffer and the "producer/consumer" model to pass messages between processes.

You will usually do that with a Mutex, to serialize all access to the shared memory, and with two Semaphores, one to count the "free" slots in the shared memory, one to count the "available" message.

This also eliminates the need for window messages, as the "consumer" thread simply waits on the proper Semaphore for the next incoming message to become available.

See also:
https://github.com/lordmulder/MUtili...IPCChannel.cpp (this is based on Qt's QSharedMemory, not "raw" Win32 API, but you get the idea!)
__________________
Go to https://standforukraine.com/ to find legitimate Ukrainian Charities 🇺🇦✊

Last edited by LoRd_MuldeR; 16th June 2019 at 17:50.
LoRd_MuldeR is offline   Reply With Quote
Old 16th June 2019, 18:51   #9  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
Are you sure you are not trying to overengineer this, my entire data sharing code is 5 lines and it's rock solid, the player has 6000 lines and I refuse to add much more.

https://github.com/stax76/mpv.net/bl...Program.cs#L41

https://github.com/stax76/mpv.net/bl...inForm.cs#L379

https://github.com/stax76/mpv.net/bl...c/Misc.cs#L366

Yes, I've counted megui (400% compared to staxrip) and your x264 launcher (25% compared to staxrip) lines of code in the past and I was surprised that so much code for so little features is needed.
stax76 is offline   Reply With Quote
Old 16th June 2019, 20:30   #10  |  Link
LoRd_MuldeR
Software Developer
 
LoRd_MuldeR's Avatar
 
Join Date: Jun 2005
Location: Last House on Slunk Street
Posts: 13,248
Quote:
Originally Posted by stax76 View Post
Are you sure you are not trying to overengineer this, my entire data sharing code is 5 lines and it's rock solid, the player has 6000 lines and I refuse to add much more.
Nope. Passing messages in a ring-buffer according to the "producer/consumer" model is a well-known standard pattern.

Of course, when using Win32 API, this will be a bit more verbose than with some "high level" language.

Anyway, I don't know if your implementation handles the case that n messages, each with its own separate payload (data), get sent to the "main" instance at the same time. But, for me, properly handling that case is a hard requirement. And, with the ring-buffer solution, we will be able to enqueue all those messages, as they are incoming and without blocking the sender process. Then our "main" instance will be able to properly process the enqueued messages, one by one.
__________________
Go to https://standforukraine.com/ to find legitimate Ukrainian Charities 🇺🇦✊

Last edited by LoRd_MuldeR; 16th June 2019 at 20:37.
LoRd_MuldeR is offline   Reply With Quote
Old 16th June 2019, 21:10   #11  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
Tell me as a user of a media player why and how you would start two files at the same time.

edit:

mpc uses wm_copydata

https://sourceforge.net/p/mpcbe/code...c/mplayerc.cpp

Last edited by stax76; 16th June 2019 at 21:41.
stax76 is offline   Reply With Quote
Old 17th June 2019, 00:55   #12  |  Link
mariush
Registered User
 
Join Date: Dec 2008
Posts: 589
select multiple files, right click, play/add to queue ... user expects filles to play one after another

or just accidental select multiple files, enter... launch 50 instances all trying read/write registry

Last edited by mariush; 17th June 2019 at 01:04.
mariush is offline   Reply With Quote
Old 17th June 2019, 10:53   #13  |  Link
stax76
Registered User
 
stax76's Avatar
 
Join Date: Jun 2002
Location: On thin ice
Posts: 6,837
It's not gonna end up like Chernobyl, I tried it:

Windows don't execute it for more than 15 files.

My player started in less than a second.

The playlist was alphabetically sorted.

No problem at all.

It's not making a real difference if I write this to registry, file or memory, in doubt I will always prefer simple and compact code. Chrome generates thousands of files, a angular app has 30 000 files...
stax76 is offline   Reply With Quote
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 14:29.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.