How to disable a specific drive - windows-services

I need to disable cdrom and the usb mass storage drivers using c# windows service. i have noticed there is a post Disable the use of CD drive (VB.NET) but it keeps ejecting the cdrom tray. does anyone know how to disable the cd rom other than using this method.????

On Vista and above you can use Group Policy settings to disable USB, CD-ROM and other types of removable storage. And you don't even need a service for that. If you cannot do this through group policy infrastructure, there is an option to set registry keys that Group Policy controls. Registry key locations are mentioned in this Vista forum post.

Check out VolumeManager defined below. It has functionality on locking volumes and disabling CD-ROM eject
public class VolumeManager
{
public string DriveLetter { private set; get; }
public IntPtr hFile { private set; get; }
public VolumeManager(string driveletter)
{
DriveLetter = driveletter;
}
public EjectState Eject()
{
if (!OpenHandle())
return EjectState.Failed;
if (Lock() && Dismount())
{
if (PreventRemoval(false) && AutoEject())
{
CloseHandle();
return EjectState.AutoEject;
}
else
{
CloseHandle();
return EjectState.RemoveSafely;
}
}
else
{
CloseHandle();
return EjectState.NoLock;
}
}
public bool OpenHandle()
{
string filename = "\\\\.\\" + DriveLetter + ":";
hFile = Win32.CreateFile(filename, Win32.GENERIC_READ | Win32.GENERIC_WRITE,
Win32.FILE_SHARE_READ | Win32.FILE_SHARE_WRITE, IntPtr.Zero, Win32.OPEN_EXISTING, 0, IntPtr.Zero);
if (hFile.ToInt32() == Win32.INVALID_HANDLE)
{
return false;
}
return true;
}
public void CloseHandle()
{
Win32.CloseHandle(hFile);
}
public bool Lock()
{
uint bytesReturned = 0;
int retry = 0;
while (retry < 20)
{
if (Win32.DeviceIoControl(hFile, Win32.FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0,
ref bytesReturned, IntPtr.Zero))
{
return true;
}
System.Threading.Thread.Sleep(250);
retry++;
}
return false;
}
public bool Dismount()
{
uint bytesReturned = 0;
if (!Win32.DeviceIoControl(hFile, Win32.FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0,
ref bytesReturned, IntPtr.Zero))
{
return false;
}
return true;
}
public bool PreventRemoval(bool prevent)
{
Win32.PREVENT_MEDIA_REMOVAL pmr = new Win32.PREVENT_MEDIA_REMOVAL();
pmr.PreventMediaRemoval = prevent;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(pmr));
Marshal.StructureToPtr(pmr, ptr, true);
uint bytesReturned = 0;
if (!Win32.DeviceIoControl(hFile, Win32.IOCTL_STORAGE_MEDIA_REMOVAL, ptr, Marshal.SizeOf(pmr), IntPtr.Zero, 0,
ref bytesReturned, IntPtr.Zero))
{
return false;
}
return true;
}
public bool AutoEject()
{
uint bytesReturned = 0;
if (!Win32.DeviceIoControl(hFile, Win32.IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0,
ref bytesReturned, IntPtr.Zero))
{
return false;
}
return true;
}
}
public enum EjectState
{
Failed,
NoVolume,
NoLock,
RemoveSafely,
AutoEject
}
public class Win32
{
public const uint FILE_DEVICE_FILE_SYSTEM = 0x00000009;
public const uint IOCTL_STORAGE_BASE = 0x0000002d;
public const uint FILE_ANY_ACCESS = 0;
public const uint FILE_READ_ACCESS = 1;
public const uint METHOD_BUFFERED = 0;
public const uint FSCTL_LOCK_VOLUME = ((FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (6 << 2) | (METHOD_BUFFERED));
public const uint FSCTL_DISMOUNT_VOLUME = ((FILE_DEVICE_FILE_SYSTEM << 16) | (FILE_ANY_ACCESS << 14) | (8 << 2) | (METHOD_BUFFERED));
public const uint IOCTL_STORAGE_MEDIA_REMOVAL = ((IOCTL_STORAGE_BASE << 16) | (FILE_READ_ACCESS << 14) | (0x0201 << 2) | (METHOD_BUFFERED));
public const uint IOCTL_STORAGE_EJECT_MEDIA = ((IOCTL_STORAGE_BASE << 16) | (FILE_READ_ACCESS << 14) | (0x0202 << 2) | (METHOD_BUFFERED));
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize,
IntPtr lpOutBuffer, uint nOutBufferSize, ref uint lpBytesReturned, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint FILE_SHARE_READ = 0x00000001;
public const uint FILE_SHARE_WRITE = 0x00000002;
public const uint OPEN_EXISTING = 3;
public const int INVALID_HANDLE = -1;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess,
uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition,
uint dwFlagsAndAttributes, IntPtr hTemplateFile);
public struct PREVENT_MEDIA_REMOVAL
{
[MarshalAs(UnmanagedType.Bool)]
public bool PreventMediaRemoval;
}
}
To disable CD-ROM eject:
string DriveLetter = "G"; // Or whatever letter you have assigned for your CD-ROM
var VolumeManager = new VolumeManager(DriveLetter);
if (VolumeManager.OpenHandle())
{
if (!VolumeManager.PreventRemoval(true))
{
// Failed to disable CD-ROM eject
VolumeManager.CloseHandle();
}
}
else
{
// Failed to access volume
}

I Have fund a solution
#region EjectMedia
const uint GENERICREAD = 0x80000000;
const uint OPENEXISTING = 3;
const uint IOCTL_STORAGE_EJECT_MEDIA = 2967560;
const int INVALID_HANDLE = -1;
private static IntPtr fileHandle;
private static uint returnedBytes;
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr CreateFile(string fileName,
uint desiredAccess,
uint shareMode,
IntPtr attributes,
uint creationDisposition,
uint flagsAndAttributes,
IntPtr templateFile);
[DllImport("kernel32", SetLastError = true)]
static extern int CloseHandle(IntPtr driveHandle);
[DllImport("kernel32", SetLastError = true)]
static extern bool DeviceIoControl(IntPtr driveHandle,
uint IoControlCode,
IntPtr lpInBuffer,
uint inBufferSize,
IntPtr lpOutBuffer,
uint outBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
#endregion
private void loop(object sender, EventArgs e)
{
DriveInfo[] allDrives = DriveInfo.GetDrives();
foreach (DriveInfo d in allDrives)
{
if (d.IsReady)
{
if (d.DriveType == DriveType.Removable || d.DriveType == DriveType.Ram || d.DriveType == DriveType.Unknown)
Eject(#"\\.\" + d.Name.Substring(0, 1) + ":");
}
}
}
public void Eject(string driveLetter)
{
try
{
fileHandle = CreateFile(driveLetter, GENERICREAD, 0, IntPtr.Zero, OPENEXISTING, 0, IntPtr.Zero);
if ((int)fileHandle != INVALID_HANDLE)
DeviceIoControl(fileHandle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, ref returnedBytes, IntPtr.Zero);
}
catch
{
EventLog.WriteEntry(Marshal.GetLastWin32Error().ToString());
}
finally
{
CloseHandle(fileHandle);
fileHandle = IntPtr.Zero;
}
}

Related

Enable broadcast on CFSocket in Xamarin.iOS

I need your help.
I have this Xamarin app, that is sending a multicast on the network using System.Net.UdpClient, but it seems pretty unstable and crashes a lot in background threads that I don't control. So I though why not go low-level.
Everything seems good except for the part of enabling the broadcast flag on the socket. In Objective-C you can do this:
setsockopt(CFSocketGetNative(cfSocket), SOL_SOCKET, SO_BROADCAST, (void *)&yes, sizeof(yes));
By looking at the mono source you'll see that the Socket class has an EnableBroadcast: https://github.com/mono/mono/blob/463cf3b5c1590df58fef43577b9a3273d5eece3d/mcs/class/System/System.Net.Sockets/Socket.cs#L195
Which inspired to this (very experimental) code:
public class NetworkHelper
{
[DllImport("libc", SetLastError = true)]
protected unsafe static extern int setsockopt(int s, int level, int optname, void* optval, uint optlen);
public unsafe static void DoMulticast()
{
var socket = new CFSocket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
var optval = 1;
var res = setsockopt(socket.Handle.ToInt32(), (int)SocketOptionLevel.Socket, (int)SocketOptionName.Broadcast, &optval, sizeof(int));
if (res < 0)
{
return;
}
}
}
It runs, but no matter what I change the setsockopt signature to, it returns -1.
TL;DR Do you think it's possible to enable the broadcast flag on a CFSocket (though Xamarin.iOS) done in the old CFNetwork.framework?
I've nailed it. I was missing the CFSocketNativeHandle like in the "native" Obj-C code, which I guess converts a CFNetwork->CFSocket into a native file descriptor pointer.
This is my full implementation (C# Extension):
public static class CFSocketExtensions
{
[DllImport(Constants.CoreFoundationLibrary)]
extern static nint CFSocketSendData(IntPtr handle, IntPtr address, IntPtr data, double timeout);
[DllImport("libc", SetLastError = true)]
extern static int setsockopt(CFSocketNativeHandle s, int level, int optname, IntPtr optval, int optlen);
[DllImport(Constants.CoreFoundationLibrary)]
extern static CFSocketNativeHandle CFSocketGetNative(IntPtr handle);
public static void SendData(this CFSocket socket, CFSocketAddress address, byte[] data, double timeout)
{
using (var buffer = new CFDataBuffer(data))
{
var error = (CFSocketError)(long)CFSocketSendData(socket.Handle, address.Handle, buffer.Handle, timeout);
if (error != CFSocketError.Success)
throw new CFSocketException(error);
}
}
public static bool EnableBroadcast(this CFSocket socket, bool enable = true)
{
int size = Marshal.SizeOf<int>();
IntPtr pBool = Marshal.AllocHGlobal(size);
Marshal.WriteInt32(pBool, 0, enable ? 1 : 0); // last parameter 0 (FALSE), 1 (TRUE)
var res = setsockopt(CFSocketGetNative(socket.Handle), (int)SocketOptionLevel.Socket, (int)SocketOptionName.Broadcast, pBool, size);
Marshal.FreeHGlobal(pBool);
return res > -1;
}
}
public class CFSocketAddress : CFDataBuffer
{
public CFSocketAddress(IPEndPoint endpoint)
: base(CreateData(endpoint))
{
}
internal static IPEndPoint EndPointFromAddressPtr(IntPtr address)
{
using (var buffer = new CFDataBuffer(address))
{
if (buffer[1] == 30)
{ // AF_INET6
int port = (buffer[2] << 8) + buffer[3];
var bytes = new byte[16];
Buffer.BlockCopy(buffer.Data, 8, bytes, 0, 16);
return new IPEndPoint(new IPAddress(bytes), port);
}
else if (buffer[1] == 2)
{ // AF_INET
int port = (buffer[2] << 8) + buffer[3];
var bytes = new byte[4];
Buffer.BlockCopy(buffer.Data, 4, bytes, 0, 4);
return new IPEndPoint(new IPAddress(bytes), port);
}
else
{
throw new ArgumentException();
}
}
}
static byte[] CreateData(IPEndPoint endpoint)
{
if (endpoint == null)
throw new ArgumentNullException("endpoint");
if (endpoint.AddressFamily == AddressFamily.InterNetwork)
{
var buffer = new byte[16];
buffer[0] = 16;
buffer[1] = 2; // AF_INET
buffer[2] = (byte)(endpoint.Port >> 8);
buffer[3] = (byte)(endpoint.Port & 0xff);
Buffer.BlockCopy(endpoint.Address.GetAddressBytes(), 0, buffer, 4, 4);
return buffer;
}
else if (endpoint.AddressFamily == AddressFamily.InterNetworkV6)
{
var buffer = new byte[28];
buffer[0] = 32;
buffer[1] = 30; // AF_INET6
buffer[2] = (byte)(endpoint.Port >> 8);
buffer[3] = (byte)(endpoint.Port & 0xff);
Buffer.BlockCopy(endpoint.Address.GetAddressBytes(), 0, buffer, 8, 16);
return buffer;
}
else
{
throw new ArgumentException();
}
}
}
public static class CFObject
{
[DllImport(Constants.CoreFoundationLibrary)]
internal extern static void CFRelease(IntPtr obj);
[DllImport(Constants.CoreFoundationLibrary)]
internal extern static IntPtr CFRetain(IntPtr obj);
}
public class CFData : INativeObject, IDisposable
{
internal IntPtr handle;
public CFData(IntPtr handle)
: this(handle, false)
{
}
public CFData(IntPtr handle, bool owns)
{
if (!owns)
CFObject.CFRetain(handle);
this.handle = handle;
}
~CFData()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public IntPtr Handle
{
get { return handle; }
}
[DllImport(Constants.CoreFoundationLibrary, EntryPoint = "CFDataGetTypeID")]
public extern static /* CFTypeID */ nint GetTypeID();
protected virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
public nint Length
{
get { return CFDataGetLength(handle); }
}
[DllImport(Constants.CoreFoundationLibrary)]
extern static /* CFIndex */ nint CFDataGetLength(/* CFDataRef */ IntPtr theData);
public byte[] GetBuffer()
{
var buffer = new byte[Length];
var ptr = CFDataGetBytePtr(handle);
Marshal.Copy(ptr, buffer, 0, buffer.Length);
return buffer;
}
[DllImport(Constants.CoreFoundationLibrary)]
extern static /* UInt8* */ IntPtr CFDataGetBytePtr(/* CFDataRef */ IntPtr theData);
/*
* Exposes a read-only pointer to the underlying storage.
*/
public IntPtr Bytes
{
get { return CFDataGetBytePtr(handle); }
}
[DllImport(Constants.CoreFoundationLibrary)]
extern static /* CFDataRef */ IntPtr CFDataCreate(/* CFAllocatorRef */ IntPtr allocator, /* UInt8* */ IntPtr bytes, /* CFIndex */ nint length);
public static CFData FromData(IntPtr buffer, nint length)
{
return new CFData(CFDataCreate(IntPtr.Zero, buffer, length), true);
}
[DllImport(Constants.CoreFoundationLibrary)]
extern static /* CFDataRef */ IntPtr CFDataCreateCopy(/* CFAllocatorRef */ IntPtr allocator, /* CFDataRef */ IntPtr theData);
public CFData Copy()
{
return new CFData(CFDataCreateCopy(IntPtr.Zero, Handle), true);
}
}
public class CFDataBuffer : IDisposable
{
byte[] buffer;
CFData data;
public CFDataBuffer(byte[] buffer)
{
this.buffer = buffer;
/*
* Copy the buffer to allow the native side to take ownership.
*/
//fixed (byte* ptr = buffer)
// data = CFData.FromData((IntPtr)ptr, buffer.Length);
GCHandle pinnedBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
data = CFData.FromData(pinnedBuffer.AddrOfPinnedObject(), buffer.Length);
pinnedBuffer.Free();
}
public CFDataBuffer(IntPtr ptr)
{
data = new CFData(ptr, false);
buffer = data.GetBuffer();
}
~CFDataBuffer()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public IntPtr Handle
{
get { return data.Handle; }
}
public byte[] Data
{
get { return buffer; }
}
public byte this[int idx]
{
get { return buffer[idx]; }
}
protected virtual void Dispose(bool disposing)
{
if (data != null)
{
data.Dispose();
data = null;
}
}
}
The only downside with this implementation is the CFSocketAddress, CFDataBuffer etc. which are defined as internal classes in the source.

How to make running exe active after hiding taskbar programmatically c#

I need to close an exe using alt+f4.
1. While running exe, user can able to save the screenshots by pressing PrintScreen at that time taskbar is made hidden.
2. After saving taskbar is shown.
3. Immediately after saving, user needs to close the exe file by Alt+f4 key press but the control goes to the windows and shows shutdown window
The exe need to get close after saving screen shots
Here is the code which is implemented.
private void GuiPane_KeyUp(object sender, KeyEventArgs e)
{
try
{
if ((e.KeyCode == Keys.PrintScreen))
{
Taskbar.Hide();
Bitmap bitmap;
Rectangle bounds = this.Bounds;
using ( bitmap = new Bitmap(bounds.Width, bounds.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
}
SaveImage(bitmap);
}
Taskbar.Show();
}
}
catch (Exception)
{
throw;
}
}
public class Taskbar
{
[DllImport("user32.dll")]
private static extern int FindWindow(string className, string windowText);
[DllImport("user32.dll")]
private static extern int ShowWindow(int hwnd, int command);
[DllImport("user32.dll")]
public static extern int FindWindowEx(int parentHandle, int childAfter, string className, int windowTitle);
[DllImport("user32.dll")]
private static extern int GetDesktopWindow();
private const int SW_HIDE = 0;
private const int SW_SHOW = 1;
protected static int Handle
{
get
{
return FindWindow("Shell_TrayWnd", "");
}
}
protected static int HandleOfStartButton
{
get
{
int handleOfDesktop = GetDesktopWindow();
int handleOfStartButton = FindWindowEx(handleOfDesktop, 0, "button", 0);
return handleOfStartButton;
}
}
private Taskbar()
{
// hide ctor
}
public static void Show()
{
ShowWindow(Handle, SW_SHOW);
ShowWindow(HandleOfStartButton, SW_SHOW);
}
public static void Hide()
{
ShowWindow(Handle, SW_HIDE);
ShowWindow(HandleOfStartButton, SW_HIDE);
}
}

Xna (MonoGame) DynamicSoundEffectInstance Buffer already Full exception

I'm making this game in MonoGame (basically Xna) that uses DynamicSoundEffectInstance class. MonoGame does not have an implementation of DynamicSoundEffectInstance yet, so I made my own:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#if MONOMAC
using MonoMac.OpenAL;
#else
using OpenTK.Audio.OpenAL;
#endif
using System.Threading;
namespace Microsoft.Xna.Framework.Audio
{
public sealed class DynamicSoundEffectInstance : IDisposable
{
private const int BUFFERCOUNT = 2;
private SoundState soundState = SoundState.Stopped;
private AudioChannels channels;
private int sampleRate;
private ALFormat format;
private bool looped = false;
private float volume = 1.0f;
private float pan = 0;
private float pitch = 0f;
private int sourceId;
private int[] bufferIds;
private int[] bufferIdsToFill;
private int currentBufferToFill;
private bool isDisposed = false;
private bool hasSourceId = false;
private Thread bufferFillerThread = null;
// Events
public event EventHandler<EventArgs> BufferNeeded;
internal void OnBufferNeeded(EventArgs args)
{
if (BufferNeeded != null)
{
BufferNeeded(this, args);
}
}
public DynamicSoundEffectInstance(int sampleRate, AudioChannels channels)
{
this.sampleRate = sampleRate;
this.channels = channels;
switch (channels)
{
case AudioChannels.Mono:
this.format = ALFormat.Mono16;
break;
case AudioChannels.Stereo:
this.format = ALFormat.Stereo16;
break;
default:
break;
}
}
public bool IsDisposed
{
get
{
return isDisposed;
}
}
public float Pan
{
get
{
return pan;
}
set
{
pan = value;
if (hasSourceId)
{
// Listener
// Pan
AL.Source(sourceId, ALSource3f.Position, pan, 0.0f, 0.1f);
}
}
}
public float Pitch
{
get
{
return pitch;
}
set
{
pitch = value;
if (hasSourceId)
{
// Pitch
AL.Source(sourceId, ALSourcef.Pitch, XnaPitchToAlPitch(pitch));
}
}
}
public float Volume
{
get
{
return volume;
}
set
{
volume = value;
if (hasSourceId)
{
// Volume
AL.Source(sourceId, ALSourcef.Gain, volume * SoundEffect.MasterVolume);
}
}
}
public SoundState State
{
get
{
return soundState;
}
}
private float XnaPitchToAlPitch(float pitch)
{
// pitch is different in XNA and OpenAL. XNA has a pitch between -1 and 1 for one octave down/up.
// openAL uses 0.5 to 2 for one octave down/up, while 1 is the default. The default value of 0 would make it completely silent.
return (float)Math.Exp(0.69314718 * pitch);
}
public void Play()
{
if (!hasSourceId)
{
bufferIds = AL.GenBuffers(BUFFERCOUNT);
sourceId = AL.GenSource();
hasSourceId = true;
}
soundState = SoundState.Playing;
if (bufferFillerThread == null)
{
bufferIdsToFill = bufferIds;
currentBufferToFill = 0;
OnBufferNeeded(EventArgs.Empty);
bufferFillerThread = new Thread(new ThreadStart(BufferFiller));
bufferFillerThread.Start();
}
AL.SourcePlay(sourceId);
}
public void Apply3D(AudioListener listener, AudioEmitter emitter)
{
Apply3D(new AudioListener[] { listener }, emitter);
}
public void Pause()
{
if (hasSourceId)
{
AL.SourcePause(sourceId);
soundState = SoundState.Paused;
}
}
public void Apply3D(AudioListener[] listeners, AudioEmitter emitter)
{
// get AL's listener position
float x, y, z;
AL.GetListener(ALListener3f.Position, out x, out y, out z);
for (int i = 0; i < listeners.Length; i++)
{
AudioListener listener = listeners[i];
// get the emitter offset from origin
Vector3 posOffset = emitter.Position - listener.Position;
// set up orientation matrix
Matrix orientation = Matrix.CreateWorld(Vector3.Zero, listener.Forward, listener.Up);
// set up our final position and velocity according to orientation of listener
Vector3 finalPos = new Vector3(x + posOffset.X, y + posOffset.Y, z + posOffset.Z);
finalPos = Vector3.Transform(finalPos, orientation);
Vector3 finalVel = emitter.Velocity;
finalVel = Vector3.Transform(finalVel, orientation);
// set the position based on relative positon
AL.Source(sourceId, ALSource3f.Position, finalPos.X, finalPos.Y, finalPos.Z);
AL.Source(sourceId, ALSource3f.Velocity, finalVel.X, finalVel.Y, finalVel.Z);
}
}
public void Dispose()
{
if (!isDisposed)
{
Stop(true);
AL.DeleteBuffers(bufferIds);
AL.DeleteSource(sourceId);
bufferIdsToFill = null;
hasSourceId = false;
isDisposed = true;
}
}
public void Stop()
{
if (hasSourceId)
{
AL.SourceStop(sourceId);
int pendingBuffers = PendingBufferCount;
if(pendingBuffers > 0)
AL.SourceUnqueueBuffers(sourceId, PendingBufferCount);
if (bufferFillerThread != null)
bufferFillerThread.Abort();
bufferFillerThread = null;
}
soundState = SoundState.Stopped;
}
public void Stop(bool immediate)
{
Stop();
}
public TimeSpan GetSampleDuration(int sizeInBytes)
{
throw new NotImplementedException();
}
public int GetSampleSizeInBytes(TimeSpan duration)
{
int size = (int)(duration.TotalMilliseconds * ((float)sampleRate / 1000.0f));
return (size + (size & 1)) * 16;
}
public void SubmitBuffer(byte[] buffer)
{
this.SubmitBuffer(buffer, 0, buffer.Length);
}
public void SubmitBuffer(byte[] buffer, int offset, int count)
{
if (bufferIdsToFill != null) {
AL.BufferData (bufferIdsToFill [currentBufferToFill], format, buffer, count, sampleRate);
AL.SourceQueueBuffer (sourceId, bufferIdsToFill [currentBufferToFill]);
currentBufferToFill++;
if (currentBufferToFill >= bufferIdsToFill.Length)
bufferIdsToFill = null;
else
OnBufferNeeded (EventArgs.Empty);
} else {
throw new Exception ("Buffer already full.");
}
}
private void BufferFiller()
{
bool done = false;
while (!done)
{
var state = AL.GetSourceState(sourceId);
if (state == ALSourceState.Stopped || state == ALSourceState.Initial)
AL.SourcePlay(sourceId);
if (bufferIdsToFill != null)
continue;
int buffersProcessed;
AL.GetSource(sourceId, ALGetSourcei.BuffersProcessed, out buffersProcessed);
if (buffersProcessed == 0)
continue;
bufferIdsToFill = AL.SourceUnqueueBuffers(sourceId, buffersProcessed);
currentBufferToFill = 0;
OnBufferNeeded(EventArgs.Empty);
}
}
public bool IsLooped
{
get
{
return looped;
}
set
{
looped = value;
}
}
public int PendingBufferCount
{
get
{
if (hasSourceId)
{
int buffersQueued;
AL.GetSource(sourceId, ALGetSourcei.BuffersQueued, out buffersQueued);
return buffersQueued;
}
return 0;
}
}
}
}
Now, I followed this tutorial on making dynamic sounds in Xna, which worked with my custom MonoGame class. However, when I run the project (Xamarin Studio 4, Mac OS X 10.8, with MonoGame 3.0.1), it throws this exception:
Buffer already full
Pointing at the code in my custom class:
public void SubmitBuffer(byte[] buffer, int offset, int count)
{
if (bufferIdsToFill != null) {
AL.BufferData (bufferIdsToFill [currentBufferToFill], format, buffer, count, sampleRate);
AL.SourceQueueBuffer (sourceId, bufferIdsToFill [currentBufferToFill]);
currentBufferToFill++;
if (currentBufferToFill >= bufferIdsToFill.Length)
bufferIdsToFill = null;
else
OnBufferNeeded (EventArgs.Empty);
} else {
throw new Exception ("Buffer already full."); //RIGHT HERE IS THE EXCEPTION
}
}
I commented out the exception, and ran it again. It played the sound, with pops in it, but it still played it. How can I clear the buffer, so it is not full? I followed this tutorial EXACTLY, so all the code I added to my project is in there.
Oh! Figured it out myself; I changed the pending buffer count from 3 to 2. My final submit buffer code was:
while(_instance.PendingBufferCount < 2)
SubmitBuffer();
Where the 2 is, used to be a 3. Now it no longer throws the exception.

Not able to show the events against same time one after other in horizontal manager in Blackberry

I am trying to get events from Blackberry Calendar. I am trying to show the events occurring at the same time one after other
like
8:00 e1
8:00 e2
as in native Calendar
But the following code shows the output as
8:00 e1 e2
in my code i have 24 hfm added to single vfm.
int size1 = 2;
horizontalFieldManager_left22 = new HorizontalFieldManager[size1];
for (int y = 0; y < size1; y++) {
horizontalFieldManager_left22[y] = new HorizontalFieldManager() {
protected boolean navigationClick(int status, int time) {
Field field = getFieldWithFocus();
Vector data = getData(listEvent);
String currentData = desc22.getText();
String currentTime = time22.getText();
if (currentData != null && currentData != "") {
UiApplication.getUiApplication().pushScreen(new EventScreen(data,currentData,currentTime));
}
return super.navigationClick(status, time);
}
protected boolean keyChar (char key, int status, int time) {
Field field = getFieldWithFocus();
return
super.keyChar(key, status, time);
}
};
int size = eventVector7.size();
LabelField[] labelField = new
LabelField[size];
for (int x = 0; x < eventVector7.size(); x++) {
labelField[x] = new
LabelField("", Field.FOCUSABLE);
String data = (String)
eventVector7.elementAt(x);
labelField[x].setText(data);
horizontalFieldManager_left22[y].add(time22);
horizontalFieldManager_left22[y].add(min22);
horizontalFieldManager_left22[y].add(new LabelField(" "));
horizontalFieldManager_left22[y].add(labelField[x]);
}
}
for (int z = 0; z < size1; z++) {
vfm.add(horizontalFieldManager_left22 [z]);
vfm.add(new SeparatorField());
}
import java.util.Hashtable;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
public class ListAllEvents extends MainScreen {
// -----------------------------------------------------------------
VerticalFieldManager mainManager;
VerticalFieldManager listVFM;
HorizontalFieldManager rowHFM[];
int row_height;
LabelField[] eventTimeLabel;
LabelField[] eventNameLabel;
public ListAllEvents() {
createUI();
createEventHashtable();
}
// -------------- Create UI --------------------------------
public void createUI() {
mainManager = new VerticalFieldManager(
VerticalFieldManager.VERTICAL_SCROLL
| VerticalFieldManager.VERTICAL_SCROLLBAR
| VerticalFieldManager.USE_ALL_HEIGHT
| VerticalFieldManager.FIELD_LEFT | DrawStyle.LEFT) {
protected void sublayout(int maxWidth, int maxHeight) {
int displayWidth = Display.getWidth();
int displayHeight = Display.getHeight();
super.sublayout(displayWidth, displayHeight);
setExtent(displayWidth, displayHeight);
}
public void paint(Graphics g) {
g.setBackgroundColor(Color.WHITE);
g.clear();
super.paint(g);
}
};
add(mainManager);
}
// ----------------------------Create List
// ----------------------------------------
public void createList(Hashtable eventHashtable) {
listVFM = new VerticalFieldManager();
rowHFM = new HorizontalFieldManager[eventHashtable.size()];
eventTimeLabel = new LabelField[eventHashtable.size()];
eventNameLabel = new LabelField[eventHashtable.size()];
row_height = 90;
int j = 0;
int row_count = 0;
if (eventHashtable.size() > 0) {
EventItem ei = null;
for (int i = 0; i < eventHashtable.size(); i++) {
Object obj = eventHashtable.get(new Integer(i));
final EventItem item = (EventItem) obj;
if (item != null) {
String str_event_time = item.event_time;
String str_event_name = item.event_name;
rowHFM[row_count] = new HorizontalFieldManager(
HorizontalFieldManager.USE_ALL_HEIGHT) {
protected void sublayout(int maxWidth, int maxHeight) {
int displayWidth = Display.getWidth();
int displayHeight = 80;
super.sublayout(displayWidth, displayHeight);
setExtent(displayWidth, displayHeight);
}
};
rowHFM[row_count].setPadding(2, 2, 2, 2);
eventTimeLabel[row_count] = new LabelField(str_event_time) {
protected void layout(int maxWidth, int maxHeight) {
int displayWidth = (int) (Display.getWidth() / 2);
int displayHeight = maxHeight;
super.layout(displayWidth, displayHeight);
setExtent(displayWidth, displayHeight);
}
};
eventTimeLabel[row_count].setPadding(5, 0, 0, 2);
eventNameLabel[row_count] = new LabelField(str_event_name) {
protected void layout(int maxWidth, int maxHeight) {
int displayWidth = (int) (Display.getWidth() / 2);
int displayHeight = maxHeight;
super.layout(displayWidth, displayHeight);
setExtent(displayWidth, displayHeight);
}
};
eventNameLabel[row_count].setPadding(5, 0, 0, 2);
rowHFM[row_count].add(eventTimeLabel[row_count]);
rowHFM[row_count].add(eventNameLabel[row_count]);
listVFM.add(rowHFM[row_count]);
}
}
}
listVFM.setPadding(5, 2, 5, 2);
mainManager.add(listVFM);
}
public void createEventHashtable() {
String event_time1 = "8:00";
String event_time2 = "8:00";
String event_name1 = "Event 1";
String event_name2 = "Event 2";
Hashtable eventHashtable = new Hashtable();
eventHashtable.put(new Integer(0), new EventItem(event_time1,
event_name1));
eventHashtable.put(new Integer(1), new EventItem(event_time2,
event_name2));
createList(eventHashtable);
}
}
public class EventItem {
String event_time;
String event_name;
public EventItem(String event_time, String event_name) {
this.event_name = event_name;
this.event_time = event_time;
}
}

J2ME/Blackberry - get audio signal amplitude level?

Is it possible in j2me to measure signal amplitude of audio record made by JSR-135 Player?
I know I can access buffer, but then what?
Target model Bold 9000, supported formats PCM and AMR. Which format I should use?
See also
Blackberry Audio Recording Sample Code
How To - Record Audio on a BlackBerry smartphone
Thank you!
Get raw PCM signal level
Use menu and trackwheel to zoom in/out and move left/right within graph.
Audio format: raw 8000 Hz 16 bit mono pcm.
Tested on Bold 9000 RIM OS 4.6
Algorythm should work in any mobile, where j2me and pcm is supported, of course implementation may require changes.
Using thread for audio recording:
class VoiceNotesRecorderThread extends Thread {
private Player _player;
private RecordControl _rcontrol;
private ByteArrayOutputStream _output;
private byte _data[];
VoiceNotesRecorderThread() {
}
public void run() {
try {
_player = Manager
.createPlayer("capture://audio?encoding=audio/basic");
_player.realize();
_rcontrol = (RecordControl) _player
.getControl("RecordControl");
_output = new ByteArrayOutputStream();
_rcontrol.setRecordStream(_output);
_rcontrol.startRecord();
_player.start();
} catch (final Exception e) {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
Dialog.inform(e.toString());
}
});
}
}
public void stop() {
try {
_rcontrol.commit();
_data = _output.toByteArray();
_output.close();
_player.close();
} catch (Exception e) {
synchronized (UiApplication.getEventLock()) {
Dialog.inform(e.toString());
}
}
}
byte[] getData() {
return _data;
}
}
And method for painting graph using byte[] buffer:
private Bitmap getGraph(byte[] buffer, int zoom, int startFrom) {
Bitmap result = new Bitmap(Display.getWidth(), Display.getHeight());
Graphics g = new Graphics(result);
g.setColor(Color.BLACK);
int xPos = 0;
int yPos = Display.getHeight() >> 1;
for (int i = startFrom; i < buffer.length; i += 2 * zoom) {
byte[] b = new byte[] { buffer[i], buffer[i + 1] };
int level = (signedShortToInt(b) * 100 / 32767);
if (100 < level) {
level -= 200;
}
g.drawPoint(xPos, yPos - level);
xPos++;
}
return result;
}
public static final int signedShortToInt(byte[] b) {
int result = (b[0] & 0xff) | (b[1] & 0xff) << 8;
return result;
}
Screen class:
class Scr extends MainScreen {
BitmapField mGraphField = new BitmapField(new Bitmap(Display.getWidth(),
Display.getHeight()));
private VoiceNotesRecorderThread m_thread;
public Scr() {
add(mGraphField);
add(new NullField(FOCUSABLE));
}
boolean mRecording = false;
private int mZoom = 1;
private int mStartFrom = 0;
byte[] mAudioData = null;
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(mRecordStopMenuItem);
menu.add(mPaintZoomIn);
menu.add(mPaintZoomOut);
menu.add(mPaintZoomToFitScreen);
menu.add(mPaintMoveRight);
menu.add(mPaintMoveLeft);
menu.add(mPaintMoveToBegin);
}
MenuItem mRecordStopMenuItem = new MenuItem("Record", 0, 0) {
public void run() {
if (!mRecording) {
m_thread = new VoiceNotesRecorderThread();
m_thread.start();
mRecording = true;
this.setText("Stop");
} else {
m_thread.stop();
mAudioData = m_thread.getData();
zoomToFitScreen();
mRecording = false;
this.setText("Record");
}
}
};
MenuItem mPaintZoomIn = new MenuItem("Zoom In", 0, 0) {
public void run() {
zoomIn();
}
};
MenuItem mPaintZoomOut = new MenuItem("Zoom Out", 0, 0) {
public void run() {
zoomOut();
}
};
MenuItem mPaintZoomToFitScreen = new MenuItem("Fit Screen", 0, 0) {
public void run() {
zoomToFitScreen();
}
};
MenuItem mPaintMoveLeft = new MenuItem("Left", 0, 0) {
public void run() {
moveLeft();
}
};
MenuItem mPaintMoveRight = new MenuItem("Right", 0, 0) {
public void run() {
moveRight();
}
};
MenuItem mPaintMoveToBegin = new MenuItem("To Begin", 0, 0) {
public void run() {
moveToBegin();
}
};
private void zoomOut() {
if (mZoom < 200)
mZoom++;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomIn() {
if (mZoom > 1)
mZoom--;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void zoomToFitScreen() {
int lenght = mAudioData.length;
mZoom = (lenght / 2) / Display.getWidth();
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveRight() {
if (mStartFrom < mAudioData.length - 30)
mStartFrom += 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveLeft() {
if (mStartFrom > 30)
mStartFrom -= 30;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
private void moveToBegin() {
mStartFrom = 0;
mGraphField.setBitmap(getGraph(mAudioData, mZoom, mStartFrom));
}
protected boolean navigationMovement(int dx, int dy, int status,
int time) {
if (dx < 0) {
moveLeft();
} else if (dx > 0) {
moveRight();
}
if (dy < 0) {
zoomIn();
} else if (dy > 0) {
zoomOut();
}
return super.navigationMovement(dx, dy, status, time);
}
}
Was helpfull:
ADC -> integer PCM file -> signal processing
SO - How is audio represented with numbers?
Convert byte array to integer
In most devices, only MID format with a single track is supported. That is the mid0 format that supports multiple instruments in one single track. I am not sure if the api provides the facility to measure the amplitude of a signal. To convert mid files to you can use Anvil Studio that has both free and pro versions
To record audio you need to use Manager.createPlayer("capture://audio"). Also leave the encoding (PCM or AMR) to the device implementation because some phones don't support PCM/AMR
Hope this helps!

Resources