Use PortAudio-Sharp bindings for easier updates

Use COSFunctions for OS-specific stuff
Add dll directories on startup (could be done in the modules itself, but this way it avoids all trouble)
This commit is contained in:
Flamefire committed 2014-03-15 17:15:13 +01:00
1 parent f0fca0baf7
commit 5316d30a7d
12 files changed
+196 -650

No files matched your search

Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration><startup><supportedRuntime version="v2.0.50727" /></startup>
<dllmap dll="PortAudio.dll" target="libportaudio.so.2" />
</configuration>
File renamed without changes.
File renamed without changes.
+89
View File
@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Vocaluxe
{
static class COSFunctions
{
#if WIN
private static bool _DefaultDllDirSet;
private static bool _UsePath;
private static bool _UseSetDllDir;
private static class CWindowsFunctions
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void AddDllDirectory(string lpPathName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void SetDllDirectory(string lpPathName);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetDefaultDllDirectories(int directoryFlags);
// ReSharper disable InconsistentNaming
public const int LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000;
// ReSharper restore InconsistentNaming
}
#endif
public static void AddEnvironmentPath(string path)
{
string newPath = Environment.GetEnvironmentVariable("PATH") ?? string.Empty;
if (newPath.Length > 0)
newPath += ";";
newPath += path;
Environment.SetEnvironmentVariable("PATH", newPath);
}
public static void AddLibrarySearchpath(string path)
{
#if WIN
if (!_DefaultDllDirSet)
{
try
{
CWindowsFunctions.SetDefaultDllDirectories(CWindowsFunctions.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
}
catch (Exception)
{
_UsePath = true;
_UseSetDllDir = true;
}
_DefaultDllDirSet = true;
}
if (_UsePath)
AddEnvironmentPath(path);
if (!_UseSetDllDir)
{
try
{
CWindowsFunctions.AddDllDirectory(path);
}
catch (Exception)
{
_UseSetDllDir = true;
}
}
if (_UseSetDllDir)
CWindowsFunctions.SetDllDirectory(path);
#endif
}
public static void SetForegroundWindow(IntPtr hWnd)
{
#if WIN
CWindowsFunctions.SetForegroundWindow(hWnd);
#endif
}
}
}
+15
View File
@@ -17,6 +17,8 @@
using System; using System;
using System.IO; using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security; using System.Security;
using Microsoft.Win32; using Microsoft.Win32;
using Vocaluxe.Base; using Vocaluxe.Base;
@@ -108,5 +110,18 @@ namespace Vocaluxe
} }
return true; return true;
} }
public static void Init()
{
#if ARCH_X86
string path = "x86";
#endif
#if ARCH_X64
string path = "x64";
#endif
path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar + path;
COSFunctions.AddLibrarySearchpath(path);
COSFunctions.AddLibrarySearchpath(path + Path.DirectorySeparatorChar + "gstreamer");
}
} }
} }
@@ -26,9 +26,6 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp
private readonly Dictionary<int, CGstreamerSharpAudioStream> _Streams = new Dictionary<int, CGstreamerSharpAudioStream>(); private readonly Dictionary<int, CGstreamerSharpAudioStream> _Streams = new Dictionary<int, CGstreamerSharpAudioStream>();
private static int _IDCount; private static int _IDCount;
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern void SetDllDirectory(string lpPathName);
public bool Init() public bool Init()
{ {
#if ARCH_X86 #if ARCH_X86
@@ -37,7 +34,7 @@ namespace Vocaluxe.Lib.Sound.Playback.GstreamerSharp
#if ARCH_X64 #if ARCH_X64
const string path = ".\\x64\\gstreamer"; const string path = ".\\x64\\gstreamer";
#endif #endif
SetDllDirectory(path); //SetDllDirectory(path);
Application.Init(); Application.Init();
Registry reg = Registry.Get(); Registry reg = Registry.Get();
reg.ScanPath(path); reg.ScanPath(path);
@@ -4,7 +4,6 @@ using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using Vocaluxe.Base; using Vocaluxe.Base;
using Vocaluxe.Lib.Sound.Playback.Decoder; using Vocaluxe.Lib.Sound.Playback.Decoder;
using Vocaluxe.Lib.Sound.PortAudio;
using VocaluxeLib; using VocaluxeLib;
namespace Vocaluxe.Lib.Sound.Playback.PortAudio namespace Vocaluxe.Lib.Sound.Playback.PortAudio
@@ -25,12 +24,12 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
private EStreamAction _AfterFadeAction; private EStreamAction _AfterFadeAction;
private CFading _Fading; private CFading _Fading;
private static CPortAudio.SPaHostApiInfo _ApiInfo; private static PortAudioSharp.PortAudio.PaHostApiInfo _ApiInfo;
private static CPortAudio.SPaDeviceInfo _OutputDeviceInfo; private static PortAudioSharp.PortAudio.PaDeviceInfo _OutputDeviceInfo;
private IntPtr _Ptr = new IntPtr(0); private IntPtr _Ptr = new IntPtr(0);
private Closeproc _Closeproc; private Closeproc _Closeproc;
private CPortAudio.PaStreamCallbackDelegate _PaStreamCallback; private PortAudioSharp.PortAudio.PaStreamCallbackDelegate _PaStreamCallback;
private int _StreamID; private int _StreamID;
private IAudioDecoder _Decoder; private IAudioDecoder _Decoder;
private float _BytesPerSecond; private float _BytesPerSecond;
@@ -202,7 +201,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
_AfterFadeAction = EStreamAction.Nothing; _AfterFadeAction = EStreamAction.Nothing;
lock (_Mutex) lock (_Mutex)
{ {
_ErrorCheck("StartStream", CPortAudio.Pa_StartStream(_Ptr)); _ErrorCheck("StartStream", PortAudioSharp.PortAudio.Pa_StartStream(_Ptr));
} }
} }
@@ -210,7 +209,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
{ {
lock (_Mutex) lock (_Mutex)
{ {
_ErrorCheck("StopStream (playback)", CPortAudio.Pa_StopStream(_Ptr)); _ErrorCheck("StopStream (playback)", PortAudioSharp.PortAudio.Pa_StopStream(_Ptr));
} }
Skip(0f); Skip(0f);
} }
@@ -241,15 +240,15 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
{ {
if (!_Initialized) if (!_Initialized)
{ {
if (_ErrorCheck("Initialize", CPortAudio.Pa_Initialize())) if (_ErrorCheck("Initialize", PortAudioSharp.PortAudio.Pa_Initialize()))
return -1; return -1;
_Initialized = true; _Initialized = true;
int hostApi = _ApiSelect(); int hostApi = _ApiSelect();
_ApiInfo = CPortAudio.PaGetHostApiInfo(hostApi); _ApiInfo = PortAudioSharp.PortAudio.Pa_GetHostApiInfo(hostApi);
_OutputDeviceInfo = CPortAudio.PaGetDeviceInfo(_ApiInfo.DefaultOutputDevice); _OutputDeviceInfo = PortAudioSharp.PortAudio.Pa_GetDeviceInfo(_ApiInfo.defaultOutputDevice);
if (_OutputDeviceInfo.DefaultLowOutputLatency < 0.1) if (_OutputDeviceInfo.defaultLowOutputLatency < 0.1)
_OutputDeviceInfo.DefaultLowOutputLatency = 0.1; _OutputDeviceInfo.defaultLowOutputLatency = 0.1;
} }
} }
@@ -278,24 +277,25 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
var data = new IntPtr(0); var data = new IntPtr(0);
var outputParams = new CPortAudio.SPaStreamParameters PortAudioSharp.PortAudio.PaStreamParameters? outputParams = new PortAudioSharp.PortAudio.PaStreamParameters
{ {
ChannelCount = format.ChannelCount, channelCount = format.ChannelCount,
Device = _ApiInfo.DefaultOutputDevice, device = _ApiInfo.defaultOutputDevice,
SampleFormat = CPortAudio.EPaSampleFormat.PaInt16, sampleFormat = PortAudioSharp.PortAudio.PaSampleFormat.paInt16,
SuggestedLatency = _OutputDeviceInfo.DefaultLowOutputLatency suggestedLatency = _OutputDeviceInfo.defaultLowOutputLatency
}; };
PortAudioSharp.PortAudio.PaStreamParameters? inputParams = null;
var bufsize = (uint)CConfig.AudioBufferSize; var bufsize = (uint)CConfig.AudioBufferSize;
lock (_Mutex) lock (_Mutex)
{ {
_ErrorCheck("OpenDefaultStream (playback)", CPortAudio.Pa_OpenStream( _ErrorCheck("OpenDefaultStream (playback)", PortAudioSharp.PortAudio.Pa_OpenStream(
out _Ptr, out _Ptr,
IntPtr.Zero, ref inputParams,
ref outputParams, ref outputParams,
format.SamplesPerSecond, format.SamplesPerSecond,
bufsize, bufsize,
CPortAudio.EPaStreamFlags.PaNoFlag, PortAudioSharp.PortAudio.PaStreamFlags.paNoFlag,
_PaStreamCallback, _PaStreamCallback,
data)); data));
} }
@@ -450,7 +450,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
{ {
lock (_Mutex) lock (_Mutex)
{ {
CPortAudio.Pa_Terminate(); PortAudioSharp.PortAudio.Pa_Terminate();
_Initialized = false; _Initialized = false;
} }
} }
@@ -462,12 +462,12 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
#endregion Threading #endregion Threading
#region Callbacks #region Callbacks
private CPortAudio.EPaStreamCallbackResult _ProcessNewData( private PortAudioSharp.PortAudio.PaStreamCallbackResult _ProcessNewData(
IntPtr input, IntPtr input,
IntPtr output, IntPtr output,
uint frameCount, uint frameCount,
ref CPortAudio.SPaStreamCallbackTimeInfo timeInfo, ref PortAudioSharp.PortAudio.PaStreamCallbackTimeInfo timeInfo,
CPortAudio.EPaStreamCallbackFlags statusFlags, PortAudioSharp.PortAudio.PaStreamCallbackFlags statusFlags,
IntPtr userData) IntPtr userData)
{ {
var buf = new byte[frameCount * _ByteCount]; var buf = new byte[frameCount * _ByteCount];
@@ -482,7 +482,7 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
{ {
Console.WriteLine(e.ToString()); Console.WriteLine(e.ToString());
} }
return CPortAudio.EPaStreamCallbackResult.PaContinue; return PortAudioSharp.PortAudio.PaStreamCallbackResult.paContinue;
} }
lock (_LockData) lock (_LockData)
@@ -534,27 +534,27 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
} }
catch (Exception e) catch (Exception e)
{ {
CLog.LogError("Error PortAudio.StreamCallback: " + e.Message); CLog.LogError("Error PortAudio.treamCallback: " + e.Message);
} }
return CPortAudio.EPaStreamCallbackResult.PaContinue; return PortAudioSharp.PortAudio.PaStreamCallbackResult.paContinue;
} }
#endregion Callbacks #endregion Callbacks
private bool _ErrorCheck(String action, CPortAudio.EPaError errorCode) private bool _ErrorCheck(String action, PortAudioSharp.PortAudio.PaError errorCode)
{ {
if (errorCode != CPortAudio.EPaError.PaNoError) if (errorCode != PortAudioSharp.PortAudio.PaError.paNoError)
{ {
if (errorCode == CPortAudio.EPaError.PaStreamIsNotStopped) if (errorCode == PortAudioSharp.PortAudio.PaError.paStreamIsNotStopped)
return false; return false;
CLog.LogError(action + " error (playback): " + CPortAudio.PaGetErrorText(errorCode)); CLog.LogError(action + " error (playback): " + PortAudioSharp.PortAudio.Pa_GetErrorText(errorCode));
if (errorCode == CPortAudio.EPaError.PaUnanticipatedHostError) if (errorCode == PortAudioSharp.PortAudio.PaError.paUnanticipatedHostError)
{ {
CPortAudio.SPaHostErrorInfo errorInfo = CPortAudio.PaGetLastHostErrorInfo(); PortAudioSharp.PortAudio.PaHostErrorInfo errorInfo = PortAudioSharp.PortAudio.Pa_GetLastHostErrorInfo();
CLog.LogError("- Host error API type: " + errorInfo.HostApiType); CLog.LogError("- Host error API type: " + errorInfo.hostApiType);
CLog.LogError("- Host error code: " + errorInfo.ErrorCode); CLog.LogError("- Host error code: " + errorInfo.errorCode);
CLog.LogError("- Host error text: " + errorInfo.ErrorText); CLog.LogError("- Host error text: " + errorInfo.errorText);
} }
return true; return true;
} }
@@ -567,13 +567,13 @@ namespace Vocaluxe.Lib.Sound.Playback.PortAudio
if (!_Initialized) if (!_Initialized)
return 0; return 0;
int selectedHostApi = CPortAudio.Pa_GetDefaultHostApi(); int selectedHostApi = PortAudioSharp.PortAudio.Pa_GetDefaultHostApi();
int apiCount = CPortAudio.Pa_GetHostApiCount(); int apiCount = PortAudioSharp.PortAudio.Pa_GetHostApiCount();
for (int i = 0; i < apiCount; i++) for (int i = 0; i < apiCount; i++)
{ {
CPortAudio.SPaHostApiInfo apiInfo = CPortAudio.PaGetHostApiInfo(i); PortAudioSharp.PortAudio.PaHostApiInfo apiInfo = PortAudioSharp.PortAudio.Pa_GetHostApiInfo(i);
if ((apiInfo.Type == CPortAudio.EPaHostApiTypeId.PaDirectSound) if ((apiInfo.type == PortAudioSharp.PortAudio.PaHostApiTypeId.paDirectSound)
|| (apiInfo.Type == CPortAudio.EPaHostApiTypeId.PaALSA)) || (apiInfo.type == PortAudioSharp.PortAudio.PaHostApiTypeId.paALSA))
selectedHostApi = i; selectedHostApi = i;
} }
return selectedHostApi; return selectedHostApi;
-558
View File
@@ -1,558 +0,0 @@
#region license
// This file is part of Vocaluxe.
//
// Vocaluxe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Vocaluxe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Runtime.InteropServices;
namespace Vocaluxe.Lib.Sound.PortAudio
{
/**
<summary>
PortAudio v.19 bindings for .NET
</summary>
*/
// ReSharper disable UnusedMember.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
// ReSharper disable MemberCanBePrivate.Global
public static class CPortAudio
{
#region **** PORTAUDIO CALLBACKS ****
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate EPaStreamCallbackResult PaStreamCallbackDelegate(
IntPtr input,
IntPtr output,
uint frameCount,
ref SPaStreamCallbackTimeInfo timeInfo,
EPaStreamCallbackFlags statusFlags,
IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void PaStreamFinishedCallbackDelegate(IntPtr userData);
#endregion
#region **** PORTAUDIO DATA STRUCTURES ****
[StructLayout(LayoutKind.Sequential)]
public struct SPaDeviceInfo
{
public int StructVersion;
[MarshalAs(UnmanagedType.LPStr)] public string Name;
public int HostApi;
public int MaxInputChannels;
public int MaxOutputChannels;
public double DefaultLowInputLatency;
public double DefaultLowOutputLatency;
public double DefaultHighInputLatency;
public double DefaultHighOutputLatency;
public double DefaultSampleRate;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "name: " + Name + "\n"
+ "hostApi: " + HostApi + "\n"
+ "maxInputChannels: " + MaxInputChannels + "\n"
+ "maxOutputChannels: " + MaxOutputChannels + "\n"
+ "defaultLowInputLatency: " + DefaultLowInputLatency + "\n"
+ "defaultLowOutputLatency: " + DefaultLowOutputLatency + "\n"
+ "defaultHighInputLatency: " + DefaultHighInputLatency + "\n"
+ "defaultHighOutputLatency: " + DefaultHighOutputLatency + "\n"
+ "defaultSampleRate: " + DefaultSampleRate;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SPaHostApiInfo
{
public int StructVersion;
public EPaHostApiTypeId Type;
[MarshalAs(UnmanagedType.LPStr)] public string Name;
public int DeviceCount;
public int DefaultInputDevice;
public int DefaultOutputDevice;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "structVersion: " + StructVersion + "\n"
+ "type: " + Type + "\n"
+ "name: " + Name + "\n"
+ "deviceCount: " + DeviceCount + "\n"
+ "defaultInputDevice: " + DefaultInputDevice + "\n"
+ "defaultOutputDevice: " + DefaultOutputDevice;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SPaHostErrorInfo
{
public EPaHostApiTypeId HostApiType;
public int ErrorCode;
[MarshalAs(UnmanagedType.LPStr)] public string ErrorText;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "hostApiType: " + HostApiType + "\n"
+ "errorCode: " + ErrorCode + "\n"
+ "errorText: " + ErrorText;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SPaStreamCallbackTimeInfo
{
public double InputBufferAdcTime;
public double CurrentTime;
public double OutputBufferDacTime;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "currentTime: " + CurrentTime + "\n"
+ "inputBufferAdcTime: " + InputBufferAdcTime + "\n"
+ "outputBufferDacTime: " + OutputBufferDacTime;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SPaStreamInfo
{
public int StructVersion;
public double InputLatency;
public double OutputLatency;
public double SampleRate;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "structVersion: " + StructVersion + "\n"
+ "inputLatency: " + InputLatency + "\n"
+ "outputLatency: " + OutputLatency + "\n"
+ "sampleRate: " + SampleRate;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct SPaStreamParameters
{
public int Device;
public int ChannelCount;
public EPaSampleFormat SampleFormat;
public double SuggestedLatency;
internal IntPtr HostApiSpecificStreamInfo;
public override string ToString()
{
return "[" + GetType().Name + "]" + "\n"
+ "device: " + Device + "\n"
+ "channelCount: " + ChannelCount + "\n"
+ "sampleFormat: " + SampleFormat + "\n"
+ "suggestedLatency: " + SuggestedLatency;
}
}
#endregion
#region **** PORTAUDIO DEFINES ****
public enum EPaDeviceIndex
{
PaNoDevice = -1,
PaUseHostApiSpecificDeviceSpecification = -2
}
public enum EPaSampleFormat : uint
{
PaFloat32 = 0x00000001,
PaInt32 = 0x00000002,
PaInt24 = 0x00000004,
PaInt16 = 0x00000008,
PaInt8 = 0x00000010,
PaUInt8 = 0x00000020,
PaCustomFormat = 0x00010000,
PaNonInterleaved = 0x80000000,
}
public const int PaFormatIsSupported = 0;
public const int PaFramesPerBufferUnspecified = 0;
public enum EPaStreamFlags : uint
{
PaNoFlag = 0,
PaClipOff = 0x00000001,
PaDitherOff = 0x00000002,
PaNeverDropInput = 0x00000004,
PaPrimeOutputBuffersUsingStreamCallback = 0x00000008,
PaPlatformSpecificFlags = 0xFFFF0000
}
public enum EPaStreamCallbackFlags : uint
{
PaInputUnderflow = 0x00000001,
PaInputOverflow = 0x00000002,
PaOutputUnderflow = 0x00000004,
PaOutputOverflow = 0x00000008,
PaPrimingOutput = 0x00000010
}
#endregion
#region **** PORTAUDIO ENUMERATIONS ****
public enum EPaError
{
PaNoError = 0,
PaNotInitialized = -10000,
PaUnanticipatedHostError,
PaInvalidChannelCount,
PaInvalidSampleRate,
PaInvalidDevice,
PaInvalidFlag,
PaSampleFormatNotSupported,
PaBadIODeviceCombination,
PaInsufficientMemory,
PaBufferTooBig,
PaBufferTooSmall,
PaNullCallback,
PaBadStreamPtr,
PaTimedOut,
PaInternalError,
PaDeviceUnavailable,
PaIncompatibleHostApiSpecificStreamInfo,
PaStreamIsStopped,
PaStreamIsNotStopped,
PaInputOverflowed,
PaOutputUnderflowed,
PaHostApiNotFound,
PaInvalidHostApi,
PaCanNotReadFromCallbackStream,
PaCanNotWriteToACallbackStream,
PaCanNotReadFromAnOutputOnlyStream,
PaCanNotWriteToAnInputOnlyStream,
PaIncompatibleStreamHostApi,
PaBadBufferPtr
}
public enum EPaHostApiTypeId : uint
{
PaInDevelopment = 0,
PaDirectSound = 1,
PaMME = 2,
PaASIO = 3,
PaSoundManager = 4,
PaCoreAudio = 5,
PaOSS = 7,
PaALSA = 8,
PaAL = 9,
PaBeOS = 10,
PaWDMKS = 11,
PaJACK = 12,
PaWASAPI = 13,
PaAudioScienceHPI = 14
}
public enum EPaStreamCallbackResult : uint
{
PaContinue = 0,
PaComplete = 1,
PaAbort = 2
}
#endregion
#region **** PORTAUDIO FUNCTIONS ****
#if ARCH_X86
#if WIN
private const string _PaDll = "x86\\portaudio_x86.dll";
#endif
#if LINUX
private const string _PaDll = "libportaudio.so.2.0.0";
#endif
#endif
#if ARCH_X64
#if WIN
private const string _PaDll = "x64\\portaudio_x64.dll";
#endif
#if LINUX
private const string _PaDll = "libportaudio.so.2.0.0";
#endif
#endif
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetVersion();
[DllImport(_PaDll, EntryPoint = "Pa_GetVersionText", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr IntPtr_Pa_GetVersionText();
public static string PaGetVersionText()
{
IntPtr strptr = IntPtr_Pa_GetVersionText();
return Marshal.PtrToStringAnsi(strptr);
}
[DllImport(_PaDll, EntryPoint = "Pa_GetErrorText", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr IntPtr_Pa_GetErrorText(EPaError errorCode);
public static string PaGetErrorText(EPaError errorCode)
{
IntPtr strptr = IntPtr_Pa_GetErrorText(errorCode);
return Marshal.PtrToStringAnsi(strptr);
}
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_Initialize();
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_Terminate();
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetHostApiCount();
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetDefaultHostApi();
[DllImport(_PaDll, EntryPoint = "Pa_GetHostApiInfo", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr IntPtr_Pa_GetHostApiInfo(int hostApi);
public static SPaHostApiInfo PaGetHostApiInfo(int hostApi)
{
IntPtr structptr = IntPtr_Pa_GetHostApiInfo(hostApi);
return (SPaHostApiInfo)Marshal.PtrToStructure(structptr, typeof(SPaHostApiInfo));
}
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_HostApiTypeIdToHostApiIndex(EPaHostApiTypeId type);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_HostApiDeviceIndexToDeviceIndex(int hostApi, int hostApiDeviceIndex);
[DllImport(_PaDll, EntryPoint = "Pa_GetLastHostErrorInfo", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr IntPtr_Pa_GetLastHostErrorInfo();
public static SPaHostErrorInfo PaGetLastHostErrorInfo()
{
IntPtr structptr = IntPtr_Pa_GetLastHostErrorInfo();
return (SPaHostErrorInfo)Marshal.PtrToStructure(structptr, typeof(SPaHostErrorInfo));
}
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetDeviceCount();
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetDefaultInputDevice();
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetDefaultOutputDevice();
[DllImport(_PaDll, EntryPoint = "Pa_GetDeviceInfo", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr IntPtr_Pa_GetDeviceInfo(int device);
public static SPaDeviceInfo PaGetDeviceInfo(int device)
{
IntPtr structptr = IntPtr_Pa_GetDeviceInfo(device);
return (SPaDeviceInfo)Marshal.PtrToStructure(structptr, typeof(SPaDeviceInfo));
}
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_IsFormatSupported(
ref SPaStreamParameters inputParameters,
ref SPaStreamParameters outputParameters,
double sampleRate);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_OpenStream(
out IntPtr stream,
ref SPaStreamParameters inputParameters,
ref SPaStreamParameters outputParameters,
double sampleRate,
uint framesPerBuffer,
EPaStreamFlags streamFlags,
PaStreamCallbackDelegate streamCallback,
IntPtr userData);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_OpenStream(
out IntPtr stream,
ref SPaStreamParameters inputParameters,
IntPtr outputParameters,
double sampleRate,
uint framesPerBuffer,
EPaStreamFlags streamFlags,
PaStreamCallbackDelegate streamCallback,
IntPtr userData);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_OpenStream(
out IntPtr stream,
IntPtr inputParameters,
ref SPaStreamParameters outputParameters,
double sampleRate,
uint framesPerBuffer,
EPaStreamFlags streamFlags,
PaStreamCallbackDelegate streamCallback,
IntPtr userData);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_OpenDefaultStream(
out IntPtr stream,
int numInputChannels,
int numOutputChannels,
uint sampleFormat,
double sampleRate,
uint framesPerBuffer,
PaStreamCallbackDelegate streamCallback,
IntPtr userData);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_CloseStream(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_SetStreamFinishedCallback(
ref IntPtr stream,
[MarshalAs(UnmanagedType.FunctionPtr)] PaStreamFinishedCallbackDelegate streamFinishedCallback);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_StartStream(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_StopStream(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_AbortStream(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_IsStreamStopped(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_IsStreamActive(IntPtr stream);
[DllImport(_PaDll, EntryPoint = "Pa_GetStreamInfo", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr IntPtr_Pa_GetStreamInfo(IntPtr stream);
public static SPaStreamInfo PaGetStreamInfo(IntPtr stream)
{
IntPtr structptr = IntPtr_Pa_GetStreamInfo(stream);
return (SPaStreamInfo)Marshal.PtrToStructure(structptr, typeof(SPaStreamInfo));
}
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern double Pa_GetStreamTime(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern double Pa_GetStreamCpuLoad(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] float[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] byte[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] sbyte[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] ushort[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] short[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] uint[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_ReadStream(
IntPtr stream,
[Out] int[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] float[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] byte[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] sbyte[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] ushort[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] short[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] uint[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_WriteStream(
IntPtr stream,
[In] int[] buffer,
uint frames);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetStreamReadAvailable(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern int Pa_GetStreamWriteAvailable(IntPtr stream);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern EPaError Pa_GetSampleSize(EPaSampleFormat format);
[DllImport(_PaDll, CallingConvention = CallingConvention.Cdecl)]
public static extern void Pa_Sleep(int msec);
#endregion
}
// ReSharper restore UnusedMember.Global
// ReSharper restore FieldCanBeMadeReadOnly.Global
// ReSharper restore MemberCanBePrivate.Global
}
@@ -21,7 +21,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Vocaluxe.Base; using Vocaluxe.Base;
using Vocaluxe.Lib.Sound.PortAudio;
namespace Vocaluxe.Lib.Sound.Record.PortAudio namespace Vocaluxe.Lib.Sound.Record.PortAudio
{ {
@@ -30,7 +29,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
private bool _Initialized; private bool _Initialized;
private List<CRecordDevice> _Devices; private List<CRecordDevice> _Devices;
private CPortAudio.PaStreamCallbackDelegate _MyRecProc; private PortAudioSharp.PortAudio.PaStreamCallbackDelegate _MyRecProc;
private IntPtr[] _RecHandle; private IntPtr[] _RecHandle;
private readonly CBuffer[] _Buffer; private readonly CBuffer[] _Buffer;
@@ -59,19 +58,19 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
if (_Initialized) if (_Initialized)
CloseAll(); CloseAll();
if (_ErrorCheck("Initialize", CPortAudio.Pa_Initialize())) if (_ErrorCheck("Initialize", PortAudioSharp.PortAudio.Pa_Initialize()))
return false; return false;
_Initialized = true; _Initialized = true;
int hostAPI = _ApiSelect(); int hostAPI = _ApiSelect();
int numDevices = CPortAudio.Pa_GetDeviceCount(); int numDevices = PortAudioSharp.PortAudio.Pa_GetDeviceCount();
for (int i = 0; i < numDevices; i++) for (int i = 0; i < numDevices; i++)
{ {
CPortAudio.SPaDeviceInfo info = CPortAudio.PaGetDeviceInfo(i); PortAudioSharp.PortAudio.PaDeviceInfo info = PortAudioSharp.PortAudio.Pa_GetDeviceInfo(i);
if (info.HostApi == hostAPI && info.MaxInputChannels > 0) if (info.hostApi == hostAPI && info.maxInputChannels > 0)
{ {
var dev = new CRecordDevice( i, info.Name,info.Name + i, info.MaxInputChannels); var dev = new CRecordDevice(i, info.name, info.name + i, info.maxInputChannels);
_Devices.Add(dev); _Devices.Add(dev);
} }
@@ -108,7 +107,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
foreach (IntPtr handle in _RecHandle) foreach (IntPtr handle in _RecHandle)
{ {
int waitcount = 0; int waitcount = 0;
while (waitcount < 5 && CPortAudio.Pa_IsStreamStopped(handle) == CPortAudio.EPaError.PaStreamIsNotStopped) while (waitcount < 5 && PortAudioSharp.PortAudio.Pa_IsStreamStopped(handle) == PortAudioSharp.PortAudio.PaError.paStreamIsNotStopped)
{ {
Thread.Sleep(1); Thread.Sleep(1);
waitcount++; waitcount++;
@@ -130,26 +129,26 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
{ {
if (active[i]) if (active[i])
{ {
var inputParams = new CPortAudio.SPaStreamParameters PortAudioSharp.PortAudio.PaStreamParameters? inputParams = new PortAudioSharp.PortAudio.PaStreamParameters
{ {
ChannelCount = _Devices[i].Channels, channelCount = _Devices[i].Channels,
Device = _Devices[i].ID, device = _Devices[i].ID,
SampleFormat = CPortAudio.EPaSampleFormat.PaInt16, sampleFormat = PortAudioSharp.PortAudio.PaSampleFormat.paInt16,
SuggestedLatency = CPortAudio.PaGetDeviceInfo(_Devices[i].ID).DefaultLowInputLatency suggestedLatency = PortAudioSharp.PortAudio.Pa_GetDeviceInfo(_Devices[i].ID).defaultLowInputLatency
}; };
PortAudioSharp.PortAudio.PaStreamParameters? outputParams = null;
if (_ErrorCheck("OpenStream (rec)", CPortAudio.Pa_OpenStream( if (_ErrorCheck("OpenStream (rec)", PortAudioSharp.PortAudio.Pa_OpenStream(
out _RecHandle[i], out _RecHandle[i],
ref inputParams, ref inputParams,
IntPtr.Zero, ref outputParams,
44100, 44100,
882, 882,
CPortAudio.EPaStreamFlags.PaNoFlag, PortAudioSharp.PortAudio.PaStreamFlags.paNoFlag,
_MyRecProc, _MyRecProc,
new IntPtr(i)))) new IntPtr(i))))
return false; return false;
if (_ErrorCheck("Start Stream (rec)", CPortAudio.Pa_StartStream(_RecHandle[i]))) if (_ErrorCheck("Start Stream (rec)", PortAudioSharp.PortAudio.Pa_StartStream(_RecHandle[i])))
return false; return false;
} }
} }
@@ -166,7 +165,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
return false; return false;
foreach (IntPtr handle in _RecHandle) foreach (IntPtr handle in _RecHandle)
CPortAudio.Pa_StopStream(handle); PortAudioSharp.PortAudio.Pa_StopStream(handle);
return true; return true;
} }
@@ -179,7 +178,7 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
if (_Initialized) if (_Initialized)
{ {
CPortAudio.Pa_Terminate(); PortAudioSharp.PortAudio.Pa_Terminate();
_Initialized = false; _Initialized = false;
} }
@@ -265,12 +264,12 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
return _Devices.AsReadOnly(); return _Devices.AsReadOnly();
} }
private CPortAudio.EPaStreamCallbackResult _MyPaStreamCallback( private PortAudioSharp.PortAudio.PaStreamCallbackResult _MyPaStreamCallback(
IntPtr input, IntPtr input,
IntPtr output, IntPtr output,
uint frameCount, uint frameCount,
ref CPortAudio.SPaStreamCallbackTimeInfo timeInfo, ref PortAudioSharp.PortAudio.PaStreamCallbackTimeInfo timeInfo,
CPortAudio.EPaStreamCallbackFlags statusFlags, PortAudioSharp.PortAudio.PaStreamCallbackFlags statusFlags,
IntPtr userData) IntPtr userData)
{ {
try try
@@ -312,20 +311,20 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
CLog.LogError("Error on Stream Callback (rec): " + e); CLog.LogError("Error on Stream Callback (rec): " + e);
} }
return CPortAudio.EPaStreamCallbackResult.PaContinue; return PortAudioSharp.PortAudio.PaStreamCallbackResult.paContinue;
} }
private bool _ErrorCheck(String action, CPortAudio.EPaError errorCode) private bool _ErrorCheck(String action, PortAudioSharp.PortAudio.PaError errorCode)
{ {
if (errorCode != CPortAudio.EPaError.PaNoError) if (errorCode != PortAudioSharp.PortAudio.PaError.paNoError)
{ {
CLog.LogError(action + " error (rec): " + CPortAudio.PaGetErrorText(errorCode)); CLog.LogError(action + " error (rec): " + PortAudioSharp.PortAudio.Pa_GetErrorText(errorCode));
if (errorCode == CPortAudio.EPaError.PaUnanticipatedHostError) if (errorCode == PortAudioSharp.PortAudio.PaError.paUnanticipatedHostError)
{ {
CPortAudio.SPaHostErrorInfo errorInfo = CPortAudio.PaGetLastHostErrorInfo(); PortAudioSharp.PortAudio.PaHostErrorInfo errorInfo = PortAudioSharp.PortAudio.Pa_GetLastHostErrorInfo();
CLog.LogError("- Host error API type: " + errorInfo.HostApiType); CLog.LogError("- Host error API type: " + errorInfo.hostApiType);
CLog.LogError("- Host error code: " + errorInfo.ErrorCode); CLog.LogError("- Host error code: " + errorInfo.errorCode);
CLog.LogError("- Host error text: " + errorInfo.ErrorText); CLog.LogError("- Host error text: " + errorInfo.errorText);
} }
return true; return true;
} }
@@ -338,13 +337,13 @@ namespace Vocaluxe.Lib.Sound.Record.PortAudio
if (!_Initialized) if (!_Initialized)
return 0; return 0;
int selectedHostApi = CPortAudio.Pa_GetDefaultHostApi(); int selectedHostApi = PortAudioSharp.PortAudio.Pa_GetDefaultHostApi();
int apiCount = CPortAudio.Pa_GetHostApiCount(); int apiCount = PortAudioSharp.PortAudio.Pa_GetHostApiCount();
for (int i = 0; i < apiCount; i++) for (int i = 0; i < apiCount; i++)
{ {
CPortAudio.SPaHostApiInfo apiInfo = CPortAudio.PaGetHostApiInfo(i); PortAudioSharp.PortAudio.PaHostApiInfo apiInfo = PortAudioSharp.PortAudio.Pa_GetHostApiInfo(i);
if ((apiInfo.Type == CPortAudio.EPaHostApiTypeId.PaDirectSound) if ((apiInfo.type == PortAudioSharp.PortAudio.PaHostApiTypeId.paDirectSound)
|| (apiInfo.Type == CPortAudio.EPaHostApiTypeId.PaALSA)) || (apiInfo.type == PortAudioSharp.PortAudio.PaHostApiTypeId.paALSA))
selectedHostApi = i; selectedHostApi = i;
} }
return selectedHostApi; return selectedHostApi;
+6 -10
View File
@@ -20,7 +20,6 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Windows.Forms; using System.Windows.Forms;
using Vocaluxe.Base; using Vocaluxe.Base;
@@ -32,12 +31,6 @@ namespace Vocaluxe
{ {
static class CMainProgram static class CMainProgram
{ {
#if WIN
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetForegroundWindow(IntPtr hWnd);
#endif
private static CSplashScreen _SplashScreen; private static CSplashScreen _SplashScreen;
[STAThread, HandleProcessCorruptedStateExceptions] [STAThread, HandleProcessCorruptedStateExceptions]
@@ -85,6 +78,7 @@ namespace Vocaluxe
if (!CProgrammHelper.CheckRequirements()) if (!CProgrammHelper.CheckRequirements())
return; return;
CProgrammHelper.Init();
CMain.Init(); CMain.Init();
CSettings.CreateFolders(); CSettings.CreateFolders();
@@ -228,13 +222,15 @@ namespace Vocaluxe
{ {
MessageBox.Show("Error on start up: " + e.Message + e.StackTrace); MessageBox.Show("Error on start up: " + e.Message + e.StackTrace);
CLog.LogError("Error on start up: " + e); CLog.LogError("Error on start up: " + e);
_SplashScreen.Close(); if (_SplashScreen != null)
_SplashScreen.Close();
_CloseProgram(); _CloseProgram();
} }
Application.DoEvents(); Application.DoEvents();
// Start Main Loop // Start Main Loop
_SplashScreen.Close(); if (_SplashScreen != null)
_SplashScreen.Close();
CVocaluxeServer.Start(); CVocaluxeServer.Start();
CDraw.MainLoop(); CDraw.MainLoop();
@@ -332,7 +328,7 @@ namespace Vocaluxe
{ {
IntPtr wnd = process.MainWindowHandle; IntPtr wnd = process.MainWindowHandle;
if (wnd != IntPtr.Zero) if (wnd != IntPtr.Zero)
SetForegroundWindow(wnd); COSFunctions.SetForegroundWindow(wnd);
} }
#endif #endif
return false; return false;
+5 -1
View File
@@ -199,6 +199,10 @@
<Reference Include="OpenTK.GLControl"> <Reference Include="OpenTK.GLControl">
<HintPath>..\Output\OpenTK.GLControl.dll</HintPath> <HintPath>..\Output\OpenTK.GLControl.dll</HintPath>
</Reference> </Reference>
<Reference Include="PortAudioSharp, Version=0.19.3.27472, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Output\PortAudioSharp.dll</HintPath>
</Reference>
<Reference Include="QRCoder, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="QRCoder, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\Output\QRCoder.dll</HintPath> <HintPath>..\Output\QRCoder.dll</HintPath>
@@ -212,6 +216,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Base\CBackgroundMusic.cs" /> <Compile Include="Base\CBackgroundMusic.cs" />
<Compile Include="COSFunctions.cs" />
<Compile Include="Lib\Sound\Playback\GstreamerSharp\CGstreamerSharpAudioStream.cs" /> <Compile Include="Lib\Sound\Playback\GstreamerSharp\CGstreamerSharpAudioStream.cs" />
<Compile Include="Lib\Sound\Playback\OpenAL\COpenAlStream.cs" /> <Compile Include="Lib\Sound\Playback\OpenAL\COpenAlStream.cs" />
<Compile Include="Lib\Sound\Playback\PortAudio\CPortAudioStream.cs" /> <Compile Include="Lib\Sound\Playback\PortAudio\CPortAudioStream.cs" />
@@ -327,7 +332,6 @@
<None Include="app.config"> <None Include="app.config">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</None> </None>
<Compile Include="Lib\Sound\PortAudio\PortAudio.cs" />
<None Include="Doc\SQLite.NET.chm" /> <None Include="Doc\SQLite.NET.chm" />
<Content Include="Website\locales\de.json"> <Content Include="Website\locales\de.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>