I need to get sound level of a specific window - c#

I'm pretty new to c#, I want to make a program that alerts me if I prefixed window sound volume become too high, for example, I have Spotify running in the background suddenly a high pitch sound then i get an alert, is this possible to do for in a low-level way that I can understand?
I already tried, an open source code that uses cscore, I did make some advancement but its way to advance for me to even keep going with that, this is where the source code I use:
Getting individual windows application current volume output level as visualized in audio Mixer
I made it, so it sends a message box with the window name that went to high on sound, but it only worked 1 time after the first time I didn't get any more message boxes, if I could just make it so it keeps sending message boxes would be perfect for me
Edit
I downloaded the source code of the program linked here, it's at the bottom of the link
I changed
var value = audioMeterInformation.GetPeakValue();
to something like 0.9
and added a messagebox around here:
using (var audioMeterInformation = session.QueryInterface<AudioMeterInformation>()) {
var value = audioMeterInformation.GetPeakValue();
if (value != 0) {
if (process != null) {
seenPids.Add(sessionid);
List<double> samples;
if (!sessionIdToAudioSamples.TryGetValue(sessionid, out samples)) {
samples = new List<double>();
sessionIdToAudioSamples[sessionid] = samples;
if(process.MainWindowTitle == "NAME OF MY WINDOW")
{
MessageBox.Show("true");
}
}
var val = audioMeterInformation.GetPeakValue();
samples.Add(val);
truncateSamples(samples);
I'm getting the message box, but just 1 time, if the high volume sound happens again it won't show the message box again, it just happens once per window.

Related

How to read text from 'simple' screenshot fast and effectively?

I'm working on a small personal application that should read some text (2 sentences at most) from a really simple Android screenshot. The text is always the same size, same font, and in approx. the same location. The background is very plain, usually a few shades of 1 color (think like bright orange fading into a little darker orange). I'm trying to figure out what would be the best way (and most importantly, the fastest way) to do this.
My first attempt involved the IronOcr C# library, and to be fair, it worked quite well! But I've noticed a few issues with it:
It's not 100% accurate
Despite having a community/trial version, it sometimes throws exceptions telling you to get a license
It takes ~400ms to read a ~600x300 pixel image, which in the case of my simple image, I consider to be rather long
As strange as it sounds, I have a feeling that libraries like IronOcr and Tesseract may just be too advanced for my needs. To improve speeds I have even written a piece of code to "treshold" my image first, making it completely black and white.
My current IronOcr settings look like this:
ImageReader = new AdvancedOcr()
{
CleanBackgroundNoise = false,
EnhanceContrast = false,
EnhanceResolution = false,
Strategy = AdvancedOcr.OcrStrategy.Fast,
ColorSpace = AdvancedOcr.OcrColorSpace.GrayScale,
DetectWhiteTextOnDarkBackgrounds = true,
InputImageType = AdvancedOcr.InputTypes.Snippet,
RotateAndStraighten = false,
ReadBarCodes = false,
ColorDepth = 1
};
And I could totally live with the results I've been getting using IronOcr, but the licensing exceptions ruin it. I also don't have $399 USD to spend on a private hobby project that won't even leave my own PC :(
But my main goal with this question is to find a better, faster or more efficient way to do this. It doesn't necessarily have to be an existing library, I'd be more than willing to make my own kind of letter-detection code that would work (only?) for screenshots like mine if someone can point me in the right direction.
I have researched about this topic and the best solution which I could find is Azure cognitive services. You can use Computer vision API to read text from an image. Here is the complete document.
How fast does it have to be?
If you are using C# I recommend the Google Cloud Vision API. You pay per request but the first 1000 per month are free (check pricing here). However, it does require a web request but I find it to be very quick
using Google.Cloud.Vision.V1;
using System;
namespace GoogleCloudSamples
{
public class QuickStart
{
public static void Main(string[] args)
{
// Instantiates a client
var client = ImageAnnotatorClient.Create();
// Load the image file into memory
var image = Image.FromFile("wakeupcat.jpg");
// Performs label detection on the image file
var response = client.DetectText(image);
foreach (var annotation in response)
{
if (annotation.Description != null)
Console.WriteLine(annotation.Description);
}
}
}
}
I find it works well for pictures and scanned documents so it should work perfectly for your situation. The SDK is also available in other languages too like Java, Python, and Node

C# - How to tell if system has virtual memory / page file on?

I have an application that consumes large amounts of RAM that I deploy to users. Some of my users are running into out of memory exception when running it - and I am noticing this is because they have their system page file turned off (because who would use 16GB of memory these days? sigh...). I want to detect if user has set this to off (or maybe some other settings) so I can warn them, because we have a lot of users come to us for support and I want to automate out some of the users because they are eating up lots of our time.
I have googled around and I can't seem to find a way to get information about page file. Specifically, I am talking about information you can see in this page in windows:
I know this is our end users problem and has nothing to do with our application (our app is designed to use up a good chunk of memory and gets a significant speed benefit). I am unsure how to detect these kinds of settings - does anyone have an idea?
You'll need to add reference to System.Management beforehand.
AllocatedBaseSize will show the current page file size in MB
using (var query = new ManagementObjectSearcher("SELECT AllocatedBaseSize FROM Win32_PageFileUsage"))
{
foreach (ManagementBaseObject obj in query.Get())
{
uint used = (uint)obj.GetPropertyValue("AllocatedBaseSize");
Console.WriteLine(used);
}
}
While MaximumSize will show the maximum page file size in MB, if the user set the maximum size (if the system managed it, the query won't return anything).
using (var query = new ManagementObjectSearcher("SELECT MaximumSize FROM Win32_PageFileSetting"))
{
foreach (ManagementBaseObject obj in query.Get())
{
uint max = (uint)obj.GetPropertyValue("MaximumSize");
Console.WriteLine(max);
}
}
If the AllocatedBaseSize is less than what your app will use and the MaximumSize is large enough for your app (or it's system managed), you'll need to consider the edge case where the storage is not enough for Windows to grow the page file. Even if there is enough space in the beginning, user could be downloading a large file on other program or rendering a large video while running your app. Consider offering 'low storage' mode where your app may run slower but don't consume as much memory.
Whilst I don't have a complete working solution for you, I think the information you are after can be retrieved from the Win32_PageFileUsage WMI class. The AllocatedBaseSize property should contain the information you are after:
AllocatedBaseSize
Data type: uint32
Access type: Read-only
Qualifiers:
MappingStrings ("Win32API|MEMORYSTATUS|dwTotalPageFile"), units
("megabytes")
Actual amount of disk space allocated for use with this
page file. This value corresponds to the range established in
Win32_PageFileSetting under the InitialSize and MaximumSize
properties, set at system startup. Example: 178
public bool IsPagingEnabled
{
get
{
var pagingFileStrings = (string[])Registry.GetValue(#"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management", "PagingFiles", null);
if (pagingFileStrings == null)
return false;
foreach (var pagingFile in pagingFileStrings)
if (pagingFile != null && !string.IsNullOrEmpty(pagingFile))
return true;
return false;
}
}

Get status of night light mode in Windows 10

I am using the desktop duplication api to grab the screen content and as it turns out, the new night light mode ('Nachtmodus' in German) is not applied in the grabbed screen content.
How do I read (if possible directly in c#) the night mode status (enabled, color shift amount)?
or
How can I tell Windows to give me the color shifted image using the desktop duplication api?
Basically, I want to know the state of what is configured inside these red boxes:
Background: I am working on an ambilight implementation and if the night light mode is enabled, the color shift is not reflected in the LEDs around my screen and so the colors are off between screen content and 'around screen'.
This method works for me in Windows 10 Version 2004
private static bool IsNightLightEnabled()
{
const string BlueLightReductionStateKey = #"SOFTWARE\Microsoft\Windows\CurrentVersion\CloudStore\Store\DefaultAccount\Current\default$windows.data.bluelightreduction.bluelightreductionstate\windows.data.bluelightreduction.bluelightreductionstate";
using (var key = Registry.CurrentUser.OpenSubKey(BlueLightReductionStateKey))
{
var data = key?.GetValue("Data");
if (data is null)
return false;
var byteData = (byte[])data;
return byteData.Length > 24 && byteData[23] == 0x10 && byteData[24] == 0x00;
}
}
You can check the output of
GetDeviceGammaRamp
Function from the Win API. Compare the output to Night Light ON and OFF and you should detect it.
Or you can try to monitor this Reg key for changes
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\$$windows.data.bluelightreduction.settings\Current
I think I found the registry entry that reflects the current night light status.
[HKEY_CURRENT_USER\Control Panel\Quick Actions\Control Center\QuickActionsStateCapture]
"Toggles"="Toggles,...,Microsoft.QuickAction.BlueLightReduction:true,..."
Although it is not very reliable because I think it requires that this particular toggle should be visible...

How to determine specific printer properties for a printer job?

I am working on some code that monitors the printer queue and then uses the event information to collect some specifics about the job, including # pages, orientation, whether or not it was color and how many copies were requested.
I catch the events using the code from Merrion Computing (which is now open source); which handles the interop.
In the case of Color, it is supposed to be stored in JOB_INFO_2.pDeviceMode.dmColor; however no matter how I submit the job (color or black and white using the printer properties printing from several apps, including word and adobe) it always indicates color. I debugged through that code directly, and the interop appears to be correct, so then I used the JobId from the event to query the print system via .NET with the code (below); and it contains exactly the same settings for copies and color.
int iJobId = e.PrintJob.JobId;
LocalPrintServer printServer = new LocalPrintServer();
PrintQueueCollection queueCollection = printServer.GetPrintQueues();
foreach (PrintQueue queue in queueCollection)
{
queue.Refresh();
if(queue.FullName.Equals(e.PrintJob.PrinterName,StringComparison.OrdinalIgnoreCase))
{
int? iPageCount;
PrintJobInfoCollection jobs = queue.GetPrintJobInfoCollection();
foreach(PrintSystemJobInfo job in jobs)
{
job.Refresh();
if(job.JobIdentifier==iJobId)
{
iPageCount = job.NumberOfPages;
}
}
//-- Found the Printer...
int? iCopyCount=queue.CurrentJobSettings.CurrentPrintTicket.CopyCount;
PageOrientation? eOrientation = queue.CurrentJobSettings.CurrentPrintTicket.PageOrientation;
OutputColor? eColor = queue.CurrentJobSettings.CurrentPrintTicket.OutputColor;
Debug.WriteLine("queue=" + queue.FullName + ", Copies=" + iCopyCount.Value + ",Color=" + eColor.ToString() + ", pagecount=" + "unk" /*iPageCount.Value*/ + ", Orientation=", eOrientation.ToString());
Debug.WriteLine("---");
}
}
Has anyone seen a reliable way to retrieve the number of copies and page count (preferably using .NET) for a specific printer job?
I
I did find this post describing the same type of problem, but there wasn't a resolution there.
Determine current print job color using C#
It should also be noted that the WMI Code from the above article also returns color.
I went in an enabled the eventlog for printing (http://www.papercut.com/kb/Main/LogPrintJobsInEventViewer). Looking at the details of the print event; the color setting is as expected "2", which indicates grayscale.
It is pretty clear that the windows subsystem is receiving the requested setting; however I have been unsuccessful to retrieve the value using WMI, System.Printing's namespace, or the interop from Merrion's print monitoring library where the values all indicate that the job is color with the correct number of pages and copies.
Is it possible to grab the spool file generated for this print to check that it is setting the dmColor setting itself?
The setting you are getting from the event log, 2, corresponds to DMCOLOR_COLOR not DMCOLOR_MONOCHROME so it seems the colour setting in the log thinks it is colour too.
It may be that the printer driver is being a bit sneaky in submitting the job as colour when it creates it but then sending a "set device settings" message in the spool that changes it to monochrome? If so there should be an SPT_DEVMODE record in the spool file.
Check this article for a spool file reader: http://www.codeproject.com/Articles/10586/EMF-Printer-Spool-File-Viewer
You need to refresh your jog until the flag IsSpooling becomes false.
for (int i = 0; i < jobs.Count(); i++)
{
try
{
int timeOut = 20000;
var jobInfo = jobs.ElementAt(i);
while (jobInfo.IsSpooling && timeOut > 0)
{
Thread.Sleep(100);
timeOut-=100;
jobInfo.Refresh();
} var pages = Math.Max(jobInfo.NumberOfPages,jobInfo.NumberOfPagesPrinted);
}
}

Access TV Tuner Stream/Feed in WPF

My team built a WPF (C#) Application that integrates with Media Center to show a video in the center of a dashboard. Essentially, the application begins recording a TV channel via Media Center, waits 10 seconds and begins playing back the file as it is being recorded. In the year since the application has launched, we have had roughly 50 help desk tickets created, 45 of which are specifically for the Media Center integration and setup.
We have determined that we need to make a major change in the implementation and architecture to remove the Media Center application all together and try to show the feed from the TV tuner directly, like you would a web cam. Unfortunately, nobody on the team here has done this before nor can we find any resources or samples of this being done.
I'm looking for working code samples that can take the stream from the TV tuner and show it in Windows Form or WPF application. I'd even be willing to buy 3rd party components out there or software. Heck, I'd even be willing to pay someone that knows how to do this to do just that!
Can you please point me in the right direction?
CODE FOR VIDEO
<MediaKit:MediaUriElement x:Name="MediaContainer" Volume="1"
Stretch="Uniform" HorizontalAlignment="Center"
UnloadedBehavior="Manual" LoadedBehavior="Play"
Height="820.00020739959" Width="1393.843"/>
CODE FOR RECORDING VIDEO
DeletePreviousRecordings();
MediaCenterControl mcc = new MediaCenterControl();
mcc.StopAllRecordings();
DateTime recordingStartTime;
DateTime endTime = DateTime.Now.Subtract(TimeSpan.FromDays(1));
int loopCount = 0;
do
{
if (loopCount++ >= 5)
{
// TODO: Show error
break;
}
recordingStartTime = DateTime.Now;
RecordingEndTime = recordingStartTime.AddMinutes(RecordDuration);
} //loop count was added below so it knew not to throw until five shots have been missed # scheduling.
while ((endTime = mcc.RecordMedia(recordingStartTime, Settings1.Default.RecordChannel, RecordDuration, loopCount)) < DateTime.Now);
if (endTime > DateTime.Now)
RecordingEndTime = endTime;
}
This can definitely be done but you would have to narrow down to one tv tuner. I actually have this working using the WinTV-HVR-1950. It took me a while but you have to get down and dirty with the hauppage drivers to get the signal and send it to the application. I'll have to look up that code but I think I may have your solution.

Categories