Merge pull request #99 from Flamefire/develop

Develop
This commit is contained in:
Stephan Sundermann committed 2014-03-14 19:47:46 +01:00
commit de6045c249
80 files changed
+2121 -1858

No files matched your search

+28 -31
View File
@@ -27,32 +27,32 @@ using System.Timers;
namespace ServerLib
{
public delegate void OnServerDiscovered(string IPAddress, string Hostname);
public delegate void OnServerDiscovered(string ipAddress, string hostname);
public class CDiscover
{
public static readonly string sTimeout = "Timeout";
public static readonly string sFinished = "Finished";
public const string Timeout = "Timeout";
public const string Finished = "Finished";
private string _Keyword;
private string _BroadcastAddress;
private int _Port;
private readonly string _Keyword;
private readonly string _BroadcastAddress;
private readonly int _Port;
private Thread _DiscoverThread;
private bool _DiscoverRunning;
private OnServerDiscovered _OnDiscovered;
private System.Timers.Timer _BroadcastTimer;
private readonly System.Timers.Timer _BroadcastTimer;
public CDiscover(int Port, string Keyword, string BroadcastAddress = "255.255.255.255")
public CDiscover(int port, string keyword, string broadcastAddress = "255.255.255.255")
{
_BroadcastAddress = BroadcastAddress;
_Port = Port;
_Keyword = Keyword;
_BroadcastAddress = broadcastAddress;
_Port = port;
_Keyword = keyword;
_DiscoverRunning = false;
_BroadcastTimer = new System.Timers.Timer();
_BroadcastTimer.Elapsed += OnBroadcastEvent;
_BroadcastTimer.Elapsed += _OnBroadcastEvent;
_BroadcastTimer.Interval = 2500;
}
@@ -67,21 +67,20 @@ namespace ServerLib
_DiscoverRunning = false;
}
public void Discover(OnServerDiscovered OnDiscovered, int Timeout = 5000)
public void Discover(OnServerDiscovered onDiscovered, int timeout = 5000)
{
if (_DiscoverRunning)
return;
_DiscoverRunning = true;
_DiscoverThread = new Thread(() => _Discover(Timeout));
_OnDiscovered = OnDiscovered;
_DiscoverThread = new Thread(() => _Discover(timeout)) {Name = "Client discover"};
_OnDiscovered = onDiscovered;
_DiscoverThread.Start();
}
private void OnBroadcastEvent(object source, ElapsedEventArgs e)
private void _OnBroadcastEvent(object source, ElapsedEventArgs e)
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
s.EnableBroadcast = true;
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) {EnableBroadcast = true};
IPAddress broadcast = IPAddress.Parse(_BroadcastAddress);
byte[] sendbuf = Encoding.UTF8.GetBytes(_Keyword);
IPEndPoint ep = new IPEndPoint(broadcast, _Port);
@@ -90,7 +89,7 @@ namespace ServerLib
s.Close();
}
private void _Discover(int Timeout)
private void _Discover(int timeout)
{
UdpClient listener = null;
Stopwatch timer = new Stopwatch();
@@ -98,27 +97,27 @@ namespace ServerLib
List<string> knownServer = new List<string>();
bool foundSomething = false;
timer.Start();
while (_DiscoverRunning && timer.ElapsedMilliseconds < Timeout * 2)
while (_DiscoverRunning && timer.ElapsedMilliseconds < timeout * 2)
{
try
{
listener = new UdpClient(_Port);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _Port);
listener.Client.ReceiveTimeout = Timeout;
IPEndPoint groupEp = new IPEndPoint(IPAddress.Any, _Port);
listener.Client.ReceiveTimeout = timeout;
byte[] bytes = listener.Receive(ref groupEP);
byte[] bytes = listener.Receive(ref groupEp);
string message = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
foundSomething = true;
if (!knownServer.Contains(groupEP.Address.ToString()))
if (!knownServer.Contains(groupEp.Address.ToString()))
{
knownServer.Add(groupEP.Address.ToString());
knownServer.Add(groupEp.Address.ToString());
if (_OnDiscovered != null)
{
IPHostEntry e = Dns.GetHostEntry(groupEP.Address);
IPHostEntry e = Dns.GetHostEntry(groupEp.Address);
string hostname = e.HostName;
_OnDiscovered(groupEP.Address.ToString(), hostname);
_OnDiscovered(groupEp.Address.ToString(), hostname);
}
}
@@ -132,10 +131,8 @@ namespace ServerLib
}
_DiscoverRunning = false;
if (!foundSomething)
_OnDiscovered(sTimeout, String.Empty);
else
_OnDiscovered(sFinished, String.Empty);
if (_OnDiscovered != null)
_OnDiscovered(!foundSomething ? Timeout : Finished, String.Empty);
}
}
}
+5 -5
View File
@@ -142,14 +142,14 @@ namespace ServerLib
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
smb.HttpGetEnabled = true;
host.Description.Behaviors.Add(smb);*/
_RegisterUrlAndCert(_BaseAddress.Port);
_RegisterUrlAndCert(_BaseAddress.Port, false);
_Host.Open();
}
catch (CommunicationException e)
{
if (e is AddressAccessDeniedException || e is AddressAlreadyInUseException)
{
_RegisterUrlAndCert(_BaseAddress.Port);
_RegisterUrlAndCert(_BaseAddress.Port, true);
try
{
_Host.Abort();
@@ -178,18 +178,18 @@ namespace ServerLib
}
}
private void _RegisterUrlAndCert(int port)
private void _RegisterUrlAndCert(int port, bool reserve)
{
#if WIN
ProcessStartInfo info = new ProcessStartInfo
{
FileName = "VocaluxeServerConfig.exe",
Arguments = port + " " + (_Encrypted ? "true" : "false"),
WorkingDirectory = Environment.CurrentDirectory,
Arguments = port + " " + (_Encrypted ? "true" : "false") + (reserve ? " reserve" : ""),
UseShellExecute = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
Verb = "runas"
};
Process p = Process.Start(info);
p.WaitForExit();
@@ -28,32 +28,27 @@ namespace ServerLib
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/sendKeyEvent?key={key}")]
void SendKeyEvent(string key);
#region profile
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getOwnProfileId")]
int GetOwnProfileId();
[OperationContract, WebInvoke(Method = "POST",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/sendProfile")]
void SendProfile(SProfileData profile);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getProfile?profileId={profileId}")]
SProfileData GetProfile(int profileId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getProfileList")]
SProfileData[] GetProfileList();
#endregion
@@ -62,7 +57,6 @@ namespace ServerLib
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/sendPhoto")]
void SendPhoto(SPhotoData photo);
#endregion
@@ -70,55 +64,46 @@ namespace ServerLib
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/login?username={username}&password={password}")]
Guid Login(string username, string password);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "")]
Stream Index();
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/js/{filename}")]
Stream GetJsFile(String filename);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/css/{filename}")]
Stream GetCssFile(String filename);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/css/images/{filename}")]
Stream GetCssImageFile(String filename);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/img/{filename}")]
Stream GetImgFile(String filename);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/locales/{filename}")]
Stream GetLocaleFile(String filename);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/delayedImage?id={id}")]
CBase64Image GetDelayedImage(String id);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/isServerOnline")]
bool IsServerOnline();
#endregion
@@ -126,19 +111,16 @@ namespace ServerLib
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getSong?songId={songId}")]
SSongInfo GetSong(int songId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getCurrentSongId")]
int GetCurrentSongId();
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getAllSongs")]
SSongInfo[] GetAllSongs();
#endregion
@@ -146,43 +128,36 @@ namespace ServerLib
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getPlaylists")]
SPlaylistInfo[] GetPlaylists();
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getPlaylist?id={playlistId}")]
SPlaylistInfo GetPlaylist(int playlistId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/addSongToPlaylist?songId={songId}&playlistId={playlistId}&duplicates={allowDuplicates}")]
void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/removeSongFromPlaylist?position={position}&playlistId={playlistId}&songId={songId}")]
void RemoveSongFromPlaylist(int position, int playlistId, int songId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/moveSongInPlaylist?newPosition={newPosition}&playlistId={playlistId}&songId={songId}")]
void MoveSongInPlaylist(int newPosition, int playlistId, int songId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/playlistContainsSong?songId={songId}&playlistId={playlistId}")]
bool PlaylistContainsSong(int songId, int playlistId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getPlaylistSongs?playlistId={playlistId}")]
SPlaylistSongInfo[] GetPlaylistSongs(int playlistId);
[OperationContract, WebInvoke(Method = "GET",
@@ -200,19 +175,16 @@ namespace ServerLib
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/getUserRole?profileId={profileId}")]
int GetUserRole(int profileId);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/setUserRole?profileId={profileId}&userRole={userRole}")]
void SetUserRole(int profileId, int userRole);
[OperationContract, WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "/hasUserRight?right={right}")]
bool HasUserRight(int right);
#endregion
}
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<ScreenOptionsRecord>
<ScreenVersion>3</ScreenVersion>
<ScreenVersion>4</ScreenVersion>
<Background1>
<!--<Type>: Background type: None, Color, Texture, Video-->
<Type>Video</Type>
@@ -216,6 +216,35 @@
<!-- <Height>: Reflection Height-->
</Text2>
<Text3>
<!--<X>, <Y>: Text position-->
<X>75</X>
<Y>347</Y>
<!--<Z>: Text position-->
<Z>0,00</Z>
<!--<H>: Text height-->
<H>27</H>
<!--<MaxW>: Maximum text width (if exists)-->
<!--<Color>: Text color from ColorScheme (high priority)-->
<!--or <R>, <G>, <B>, <A> (lower priority)-->
<Color>StaticColor</Color>
<!--<SColor>: Selected Text color from ColorScheme (high priority)-->
<!--or <SR>, <SG>, <SB>, <SA> (lower priority)-->
<SColor>TextSColor</SColor>
<!--<Align>: Text align horizontal: Left, Center, Right-->
<Align>Left</Align>
<!--<ResizeAlign>: Text align vertical (on downsizing): Top, Center, Bottom-->
<HAlign>Center</HAlign>
<!--<Style>: Text style: Normal, Italic, Bold, BoldItalic-->
<Style>Bold</Style>
<!--<Font>: Text font name-->
<Font>Outline</Font>
<!--<Text>: Nothing or translation tag-->
<Text>TR_SCREENORECORD_MIC_DELAY</Text>
<!--<Reflection> If exists:-->
<!-- <Space>: Reflection Space-->
<!-- <Height>: Reflection Height-->
</Text3>
<TextChannel1>
<!--<X>, <Y>: Text position-->
<X>75</X>
<Y>227</Y>
@@ -243,8 +272,8 @@
<!--<Reflection> If exists:-->
<!-- <Space>: Reflection Space-->
<!-- <Height>: Reflection Height-->
</Text3>
<Text4>
</TextChannel1>
<TextChannel2>
<!--<X>, <Y>: Text position-->
<X>75</X>
<Y>287</Y>
@@ -272,36 +301,7 @@
<!--<Reflection> If exists:-->
<!-- <Space>: Reflection Space-->
<!-- <Height>: Reflection Height-->
</Text4>
<Text5>
<!--<X>, <Y>: Text position-->
<X>75</X>
<Y>347</Y>
<!--<Z>: Text position-->
<Z>0,00</Z>
<!--<H>: Text height-->
<H>27</H>
<!--<MaxW>: Maximum text width (if exists)-->
<!--<Color>: Text color from ColorScheme (high priority)-->
<!--or <R>, <G>, <B>, <A> (lower priority)-->
<Color>StaticColor</Color>
<!--<SColor>: Selected Text color from ColorScheme (high priority)-->
<!--or <SR>, <SG>, <SB>, <SA> (lower priority)-->
<SColor>TextSColor</SColor>
<!--<Align>: Text align horizontal: Left, Center, Right-->
<Align>Left</Align>
<!--<ResizeAlign>: Text align vertical (on downsizing): Top, Center, Bottom-->
<HAlign>Center</HAlign>
<!--<Style>: Text style: Normal, Italic, Bold, BoldItalic-->
<Style>Bold</Style>
<!--<Font>: Text font name-->
<Font>Outline</Font>
<!--<Text>: Nothing or translation tag-->
<Text>TR_SCREENORECORD_MIC_DELAY</Text>
<!--<Reflection> If exists:-->
<!-- <Space>: Reflection Space-->
<!-- <Height>: Reflection Height-->
</Text5>
</TextChannel2>
<TextWarning>
<!--<X>, <Y>: Text position-->
<X>640</X>
@@ -6,4 +6,7 @@ Version 2:
Add:
<EqualizerChannel1> and <EqualizerChannel2>.
This is a new theme-element. Check ScreenOptionsRecord.xml for style-possibilities.
++++++++++
++++++++++
Version 4:
Rename Text 3/4 to TextChannel1/2
Rename Text5 to Text3
+7 -9
View File
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using VocaluxeLib;
@@ -39,7 +38,7 @@ namespace Vocaluxe.Base
private static int _Video = -1;
private static CTexture _CurrentVideoTexture;
private static readonly Stopwatch _FadeTimer = new Stopwatch();
private static CFading _VideoFading;
private static bool _VideoEnabled;
private static bool _OwnMusicAdded;
@@ -442,12 +441,12 @@ namespace Vocaluxe.Base
float vtime;
if (CVideo.GetFrame(_Video, ref _CurrentVideoTexture, CSound.GetPosition(_CurrentMusicStream), out vtime))
{
if (_FadeTimer.ElapsedMilliseconds <= 3000L)
_CurrentVideoTexture.Color.A = _FadeTimer.ElapsedMilliseconds / 3000f;
else
if (_VideoFading != null)
{
_CurrentVideoTexture.Color.A = 1f;
_FadeTimer.Stop();
bool finished;
_CurrentVideoTexture.Color.A = _VideoFading.GetValue(out finished);
if (finished)
_VideoFading = null;
}
return _CurrentVideoTexture;
}
@@ -469,8 +468,7 @@ namespace Vocaluxe.Base
CVideo.Skip(_Video, _CurrentPlaylistElement.Start, _CurrentPlaylistElement.VideoGap);
else
CVideo.Skip(_Video, 0f, _CurrentPlaylistElement.VideoGap);
_FadeTimer.Reset();
_FadeTimer.Start();
_VideoFading = new CFading(0f, 1f, 3f);
}
}
+4 -4
View File
@@ -60,10 +60,10 @@ namespace Vocaluxe.Base
public static int ScreenW = 1024;
public static int ScreenH = 576;
public static int BorderLeft = 0;
public static int BorderRight = 0;
public static int BorderTop = 0;
public static int BorderBottom = 0;
public static int BorderLeft;
public static int BorderRight;
public static int BorderTop;
public static int BorderBottom;
public static EAntiAliasingModes AAMode = EAntiAliasingModes.X0;
+11 -37
View File
@@ -24,10 +24,7 @@ namespace Vocaluxe.Base
{
class CCursor
{
private readonly Stopwatch _CursorFadingTimer = new Stopwatch();
private float _CursorTargetAlpha = 1f;
private float _CursorStartAlpha;
private float _CursorFadingTime = 0.5f;
private CFading _Fading;
private CTexture _Cursor;
private readonly Stopwatch _Movetimer = new Stopwatch();
@@ -52,28 +49,19 @@ namespace Vocaluxe.Base
public void Draw()
{
if (_Movetimer.IsRunning && _Movetimer.ElapsedMilliseconds / 1000f > CSettings.MouseMoveOffTime)
if (_Movetimer.IsRunning && _Movetimer.ElapsedMilliseconds > CSettings.MouseMoveOffTime)
{
_Movetimer.Stop();
_Fade(0f, 0.5f);
}
if (_CursorFadingTimer.IsRunning)
if (_Fading != null)
{
float t = _CursorFadingTimer.ElapsedMilliseconds / 1000f;
if (t < _CursorFadingTime)
{
if (_CursorTargetAlpha >= _CursorStartAlpha)
_Cursor.Color.A = _CursorStartAlpha + (_CursorTargetAlpha - _CursorStartAlpha) * t / _CursorFadingTime;
else
_Cursor.Color.A = (_CursorStartAlpha - _CursorTargetAlpha) * (1f - t / _CursorFadingTime);
}
else
{
_CursorFadingTimer.Stop();
_Cursor.Color.A = _CursorTargetAlpha;
}
bool finished;
_Cursor.Color.A = _Fading.GetValue(out finished);
if (finished)
_Fading = null;
}
if (Visible && (CSettings.GameState == EGameState.EditTheme || ShowCursor))
@@ -85,11 +73,10 @@ namespace Vocaluxe.Base
if (Math.Abs(_Cursor.Rect.X - x) > CSettings.MouseMoveDiffMin ||
Math.Abs(_Cursor.Rect.Y - y) > CSettings.MouseMoveDiffMin)
{
if (_CursorTargetAlpha < 0.01)
if (!IsActive)
_Fade(1f, 0.2f);
_Movetimer.Reset();
_Movetimer.Start();
_Movetimer.Restart();
CSettings.MouseActive();
}
@@ -130,26 +117,13 @@ namespace Vocaluxe.Base
public void FadeIn()
{
_Movetimer.Reset();
_Movetimer.Start();
_Movetimer.Restart();
_Fade(1f, 0.2f);
}
private void _Fade(float targetAlpha, float time)
{
_CursorFadingTimer.Stop();
_CursorFadingTimer.Reset();
if (targetAlpha >= 0f && targetAlpha <= 1f)
_CursorTargetAlpha = targetAlpha;
else
_CursorTargetAlpha = 1f;
if (time >= 0f)
_CursorFadingTime = time;
_CursorStartAlpha = _Cursor.Color.A;
_CursorFadingTimer.Start();
_Fading = new CFading(_Cursor.Color.A, targetAlpha, time);
}
}
}
+106 -106
View File
@@ -63,8 +63,16 @@ namespace Vocaluxe.Base
_CreditsRessourcesFilePath = Path.Combine(Environment.CurrentDirectory, CSettings.FileCreditsRessourcesDB);
_InitHighscoreDB();
_InitCoverDB();
_InitCreditsRessourcesDB();
if (!_InitCoverDB())
{
CLog.LogError("Error initializing Cover-DB", true, true);
return;
}
if (!_InitCreditsRessourcesDB())
{
CLog.LogError("Error initializing Cover-DB", true, true);
return;
}
GC.Collect();
}
@@ -93,26 +101,6 @@ namespace Vocaluxe.Base
return _GetDataBaseSongInfos(songID, out sArtist, out sTitle, out numPlayed, out dateAdded, _HighscoreFilePath);
}
public static void IncreaseSongCounter(SPlayer player)
{
using (var connection = new SQLiteConnection())
{
connection.ConnectionString = "Data Source=" + _HighscoreFilePath;
try
{
connection.Open();
}
catch (Exception) {}
using (var command = new SQLiteCommand(connection))
{
int dataBaseSongID = _GetDataBaseSongID(player, command);
_IncreaseSongCounter(dataBaseSongID, command);
}
}
}
public static void IncreaseSongCounter(int dataBaseSongID)
{
using (var connection = new SQLiteConnection())
@@ -170,11 +158,27 @@ namespace Vocaluxe.Base
return -1;
}
int medley = 0;
int duet = 0;
int shortSong = 0;
switch (player.GameMode)
{
case EGameMode.TR_GAMEMODE_MEDLEY:
medley = 1;
break;
case EGameMode.TR_GAMEMODE_DUET:
duet = 1;
break;
case EGameMode.TR_GAMEMODE_SHORTSONG:
shortSong = 1;
break;
}
using (var command = new SQLiteCommand(connection))
{
int dataBaseSongID = CSongs.GetSong(player.SongID).DataBaseSongID;
return _AddScore(CProfiles.GetPlayerName(player.ProfileID), (int)Math.Round(player.Points), player.VoiceNr, player.DateTicks, player.Medley ? 1 : 0,
player.Duet ? 1 : 0, player.ShortSong ? 1 : 0, (int)CProfiles.GetDifficulty(player.ProfileID), dataBaseSongID, command);
return _AddScore(CProfiles.GetPlayerName(player.ProfileID), (int)Math.Round(player.Points), player.VoiceNr, player.DateTicks, medley,
duet, shortSong, (int)CProfiles.GetDifficulty(player.ProfileID), dataBaseSongID, command);
}
}
}
@@ -243,70 +247,74 @@ namespace Vocaluxe.Base
return lastInsertID;
}
public static void LoadScore(out List<SScores> scores, SPlayer player)
public static List<SDBScoreEntry> LoadScore(int songID, EGameMode gameMode)
{
var scores = new List<SDBScoreEntry>();
using (var connection = new SQLiteConnection())
{
connection.ConnectionString = "Data Source=" + _HighscoreFilePath;
scores = new List<SScores>();
try
{
connection.Open();
}
catch (Exception)
{
return;
return scores;
}
using (var command = new SQLiteCommand(connection))
{
int medley = 0;
if (player.Medley)
medley = 1;
int duet = 0;
if (player.Duet)
duet = 1;
int shortSong = 0;
if (player.ShortSong)
shortSong = 1;
int dataBaseSongID = _GetDataBaseSongID(player, command);
if (dataBaseSongID >= 0)
switch (gameMode)
{
command.CommandText = "SELECT PlayerName, Score, Date, Difficulty, LineNr, id FROM Scores " +
"WHERE [SongID] = @SongID AND [Medley] = @Medley AND [Duet] = @Duet AND [ShortSong] = @ShortSong " +
"ORDER BY [Score] DESC";
command.Parameters.Add("@SongID", DbType.Int32, 0).Value = dataBaseSongID;
command.Parameters.Add("@Medley", DbType.Int32, 0).Value = medley;
command.Parameters.Add("@Duet", DbType.Int32, 0).Value = duet;
command.Parameters.Add("@ShortSong", DbType.Int32, 0).Value = shortSong;
case EGameMode.TR_GAMEMODE_MEDLEY:
medley = 1;
break;
case EGameMode.TR_GAMEMODE_DUET:
duet = 1;
break;
case EGameMode.TR_GAMEMODE_SHORTSONG:
shortSong = 1;
break;
}
SQLiteDataReader reader = command.ExecuteReader();
if (reader != null && reader.HasRows)
int dataBaseSongID = _GetDataBaseSongID(songID, command);
if (dataBaseSongID < 0)
return scores;
command.CommandText = "SELECT PlayerName, Score, Date, Difficulty, LineNr, id FROM Scores " +
"WHERE [SongID] = @SongID AND [Medley] = @Medley AND [Duet] = @Duet AND [ShortSong] = @ShortSong " +
"ORDER BY [Score] DESC";
command.Parameters.Add("@SongID", DbType.Int32, 0).Value = dataBaseSongID;
command.Parameters.Add("@Medley", DbType.Int32, 0).Value = medley;
command.Parameters.Add("@Duet", DbType.Int32, 0).Value = duet;
command.Parameters.Add("@ShortSong", DbType.Int32, 0).Value = shortSong;
SQLiteDataReader reader = command.ExecuteReader();
if (reader != null && reader.HasRows)
{
while (reader.Read())
{
while (reader.Read())
{
var score = new SScores
{
Name = reader.GetString(0),
Score = reader.GetInt32(1),
Date = new DateTime(reader.GetInt64(2)).ToString("dd/MM/yyyy"),
Difficulty = (EGameDifficulty)reader.GetInt32(3),
LineNr = reader.GetInt32(4),
ID = reader.GetInt32(5)
};
var score = new SDBScoreEntry
{
Name = reader.GetString(0),
Score = reader.GetInt32(1),
Date = new DateTime(reader.GetInt64(2)).ToString("dd/MM/yyyy"),
Difficulty = (EGameDifficulty)reader.GetInt32(3),
VoiceNr = reader.GetInt32(4),
ID = reader.GetInt32(5)
};
scores.Add(score);
}
reader.Dispose();
scores.Add(score);
}
reader.Dispose();
}
}
}
return scores;
}
private static void _IncreaseSongCounter(int dataBaseSongID, SQLiteCommand command)
@@ -316,9 +324,9 @@ namespace Vocaluxe.Base
command.ExecuteNonQuery();
}
private static int _GetDataBaseSongID(SPlayer player, SQLiteCommand command)
private static int _GetDataBaseSongID(int songID, SQLiteCommand command)
{
CSong song = CSongs.GetSong(player.SongID);
CSong song = CSongs.GetSong(songID);
if (song == null)
return -1;
@@ -430,21 +438,35 @@ namespace Vocaluxe.Base
{
if (File.Exists(_HighscoreFilePath))
{
_CreateOrConvert(oldDBFilePath);
_CreateOrConvert(_HighscoreFilePath);
_ImportData(oldDBFilePath);
File.Delete(oldDBFilePath);
if (!_CreateOrConvert(oldDBFilePath))
{
CLog.LogError("Cannot init Highscore DB: Error opening database: " + oldDBFilePath, true, true);
return;
}
if (!_CreateOrConvert(_HighscoreFilePath))
{
CLog.LogError("Cannot init Highscore DB: Error opening database: " + _HighscoreFilePath, true, true);
return;
}
if (!_ImportData(oldDBFilePath))
{
CLog.LogError("Cannot init Highscore DB: Error importing data", true, true);
return;
}
}
else
{
File.Copy(oldDBFilePath, _HighscoreFilePath);
_CreateOrConvert(_HighscoreFilePath);
File.Delete(oldDBFilePath);
if (!_CreateOrConvert(_HighscoreFilePath))
{
CLog.LogError("Cannot init Highscore DB: Error opening database: " + _HighscoreFilePath, true, true);
return;
}
}
File.Delete(oldDBFilePath);
}
else
_CreateOrConvert(_HighscoreFilePath);
else if (!_CreateOrConvert(_HighscoreFilePath))
CLog.LogError("Cannot init Highscore DB: Error opening database: " + _HighscoreFilePath, true, true);
}
private static void _CreateHighscoreDB(string filePath)
@@ -525,6 +547,7 @@ namespace Vocaluxe.Base
/// <returns></returns>
private static bool _CreateOrConvert(string filePath)
{
bool result = true;
using (var connection = new SQLiteConnection())
{
connection.ConnectionString = "Data Source=" + filePath;
@@ -565,46 +588,24 @@ namespace Vocaluxe.Base
}
catch (Exception) {}
if (reader == null)
if (reader == null || reader.FieldCount == 0)
{
// create new database/tables
if (version == 1)
{
//Check for USDX 1.1 DB
_CreateHighscoreDBV1(filePath);
_ConvertFrom110(filePath);
_UpdateDatabase(1, connection);
_UpdateDatabase(2, connection);
result &= !_ConvertFrom110(filePath);
result &= _UpdateDatabase(1, connection);
result &= _UpdateDatabase(2, connection);
}
else if (version == 0 && scoresTableExists)
{
//Check for USDX 1.01 or CMD Mod DB
_CreateHighscoreDBV1(filePath);
_ConvertFrom101(filePath);
_UpdateDatabase(1, connection);
_UpdateDatabase(2, connection);
}
else
_CreateHighscoreDB(filePath);
}
else if (reader.FieldCount == 0)
{
// create new database/tables
if (version == 1)
{
//Check for USDX 1.1 DB
_CreateHighscoreDBV1(filePath);
_ConvertFrom110(filePath);
_UpdateDatabase(1, connection);
_UpdateDatabase(2, connection);
}
else if (version == 0 && scoresTableExists)
{
//Check for USDX 1.01 or CMD Mod DB
_CreateHighscoreDBV1(filePath);
_ConvertFrom101(filePath);
_UpdateDatabase(1, connection);
_UpdateDatabase(2, connection);
result &= _ConvertFrom101(filePath);
result &= _UpdateDatabase(1, connection);
result &= _UpdateDatabase(2, connection);
}
else
_CreateHighscoreDB(filePath);
@@ -616,7 +617,7 @@ namespace Vocaluxe.Base
if (currentVersion < CSettings.DatabaseHighscoreVersion)
{
// update database
_UpdateDatabase(currentVersion, connection);
result &= _UpdateDatabase(currentVersion, connection);
}
}
@@ -625,7 +626,7 @@ namespace Vocaluxe.Base
}
}
return true;
return result;
}
/// <summary>
@@ -972,8 +973,7 @@ namespace Vocaluxe.Base
lastDateAdded = dateAdded;
}
}
if (reader != null)
reader.Dispose();
reader.Dispose();
foreach (int id in ids)
_IncreaseSongCounter(id, command);
+15 -25
View File
@@ -131,7 +131,7 @@ namespace Vocaluxe.Base
public static void NextRound()
{
_SongQueue.NextRound(Players);
_SongQueue.StartNextRound(Players);
}
public static bool IsFinished()
@@ -149,14 +149,14 @@ namespace Vocaluxe.Base
return _SongQueue.GetSong();
}
public static CSong GetSong(int num)
public static CSong GetSong(int round)
{
return _SongQueue.GetSong(num);
return _SongQueue.GetSong(round);
}
public static EGameMode GetGameMode(int num)
public static EGameMode GetGameMode(int round)
{
return _SongQueue.GetGameMode(num);
return _SongQueue.GetGameMode(round);
}
public static int GetNumSongs()
@@ -197,9 +197,7 @@ namespace Vocaluxe.Base
Players[i].CurrentLine = -1;
Players[i].CurrentNote = -1;
Players[i].SongID = -1;
Players[i].Medley = false;
Players[i].Duet = false;
Players[i].ShortSong = false;
Players[i].GameMode = EGameMode.TR_GAMEMODE_NORMAL;
Players[i].DateTicks = DateTime.Now.Ticks;
Players[i].SongFinished = false;
}
@@ -210,7 +208,7 @@ namespace Vocaluxe.Base
public static void UpdatePoints(float time)
{
bool DEBUG_HIT = false;
const bool DEBUG_HIT = false;
CSong song = _SongQueue.GetSong();
@@ -276,8 +274,6 @@ namespace Vocaluxe.Base
{
int tone = notes[note].Tone;
int tonePlayer = CSound.RecordGetTone(p);
if (DEBUG_HIT)
tonePlayer = tone;
while (tonePlayer - tone > 6)
tonePlayer -= 12;
@@ -364,7 +360,7 @@ namespace Vocaluxe.Base
public static void ResetToLastLine(int soundStream, int vidStream)
{
float[] time = GetLastSungLineStart();
float[] time = _GetLastSungLineStart();
ResetToTime(time[0], time[1], soundStream, vidStream);
}
@@ -413,23 +409,20 @@ namespace Vocaluxe.Base
}
Players[p].SungLines.RemoveRange(deleteLine, Players[p].SungLines.Count - deleteLine);
}
//CSong song = GetSong();
//for (int i = 0; i < GetSong().Notes.Voices[0].Lines.Length; i++)
// CLog.LogError((i + 1) + ". " + song.Notes.Voices[0].Lines[i].NoteCount + " - " + Players[0].SungLines[i].NoteCount);
CSound.SetPosition(soundStream, time);
CVideo.Skip(vidStream, time, GetSong().VideoGap);
}
private static float[] GetLastSungLineStart()
private static float[] _GetLastSungLineStart()
{
return GetNoteTimeBeforeBeat(CurrentBeat);
return _GetNoteTimeBeforeBeat(CurrentBeat);
}
private static float[] GetNoteTimeBeforeBeat(int beat)
private static float[] _GetNoteTimeBeforeBeat(int beat)
{
CSong song = GetSong();
int StartBeat = (int)Math.Floor(beat - GetBeatFromTime(CSettings.PauseResetTime, song.BPM, 0f));
int startBeat = (int)Math.Floor(beat - GetBeatFromTime(CSettings.PauseResetTime, song.BPM, 0f));
int lastStart = 0;
int nextStart = 0;
foreach (CVoice voice in song.Notes.Voices)
@@ -441,16 +434,13 @@ namespace Vocaluxe.Base
{
foreach (CSongNote note in line.Notes)
{
if (note.StartBeat > StartBeat)
if (note.StartBeat > startBeat)
{
nextStartNote = note.StartBeat;
break;
}
else
{
voiceStart = note.StartBeat;
lastEnd = note.EndBeat;
}
voiceStart = note.StartBeat;
lastEnd = note.EndBeat;
}
if (nextStartNote > 0)
break;
+35 -69
View File
@@ -30,13 +30,11 @@ namespace Vocaluxe.Base
{
static class CGraphics
{
private static bool _Fading;
private static Stopwatch _FadingTimer;
private static CFading _Fading;
private static readonly CCursor _Cursor = new CCursor();
private static float _GlobalAlpha;
private static float _ZOffset;
private static IMenu _OldScreen;
private static EScreens _CurrentScreen;
private static EScreens _NextScreen;
private static EPopupScreens _CurrentPopupScreen;
@@ -98,7 +96,6 @@ namespace Vocaluxe.Base
_CurrentScreen = EScreens.ScreenLoad;
_NextScreen = EScreens.ScreenNull;
_CurrentPopupScreen = EPopupScreens.NoPopup;
_FadingTimer = new Stopwatch();
_VolumePopupTimer = new Stopwatch();
_GlobalAlpha = 1f;
@@ -198,11 +195,9 @@ namespace Vocaluxe.Base
public static bool Draw()
{
if ((_NextScreen != EScreens.ScreenNull) && !_Fading)
if (_NextScreen != EScreens.ScreenNull && _Fading == null)
{
_Fading = true;
_FadingTimer.Reset();
_FadingTimer.Start();
_Fading = new CFading(0f, 1f, CConfig.FadeTime);
if (_NextScreen == EScreens.ScreenPartyDummy)
{
@@ -216,49 +211,29 @@ namespace Vocaluxe.Base
HidePopup(EPopupScreens.PopupPlayerControl);
}
if (_Fading)
if (_Fading != null)
{
long fadeTime = (long)(CConfig.FadeTime * 1000);
bool finished;
float newAlpha = _Fading.GetValue(out finished);
if ((_FadingTimer.ElapsedMilliseconds < fadeTime) && (CConfig.FadeTime > 0))
if (!finished)
{
long ms = 1;
if (_FadingTimer.ElapsedMilliseconds > 0)
ms = _FadingTimer.ElapsedMilliseconds;
float factor = (float)ms / fadeTime;
_GlobalAlpha = 1f; // -factor / 100f;
_GlobalAlpha = 1f; // -newAlpha / 100f;
_ZOffset = CSettings.ZFar / 2;
if (_CurrentScreen == EScreens.ScreenPartyDummy)
{
CFonts.PartyModeID = CParty.CurrentPartyModeID;
_OldScreen.Draw();
CFonts.PartyModeID = -1;
}
else
_OldScreen.Draw();
_DrawScreen(_CurrentScreen);
_GlobalAlpha = factor;
_GlobalAlpha = newAlpha;
_ZOffset = 0f;
if (_NextScreen == EScreens.ScreenPartyDummy)
{
CFonts.PartyModeID = CParty.CurrentPartyModeID;
_Screens[(int)_NextScreen].Draw();
CFonts.PartyModeID = -1;
}
else
_Screens[(int)_NextScreen].Draw();
_DrawScreen(_NextScreen);
_GlobalAlpha = 1f;
}
else
{
_Screens[(int)_CurrentScreen].OnClose();
GC.Collect();
_CurrentScreen = _NextScreen;
_NextScreen = EScreens.ScreenNull;
if (CBackgroundMusic.IsPlaying)
@@ -266,32 +241,13 @@ namespace Vocaluxe.Base
_Screens[(int)_CurrentScreen].OnShowFinish();
_Screens[(int)_CurrentScreen].ProcessMouseMove(_Cursor.X, _Cursor.Y);
if (_CurrentScreen == EScreens.ScreenPartyDummy)
{
CFonts.PartyModeID = CParty.CurrentPartyModeID;
_Screens[(int)_CurrentScreen].Draw();
CFonts.PartyModeID = -1;
}
else
_Screens[(int)_CurrentScreen].Draw();
_DrawScreen(_CurrentScreen);
_Fading = false;
_FadingTimer.Stop();
_Fading = null;
}
}
else
{
if (_CurrentScreen == EScreens.ScreenPartyDummy)
{
CFonts.PartyModeID = CParty.CurrentPartyModeID;
_Screens[(int)_CurrentScreen].Draw();
CFonts.PartyModeID = -1;
}
else
_Screens[(int)_CurrentScreen].Draw();
_OldScreen = _Screens[(int)_CurrentScreen];
}
_DrawScreen(_CurrentScreen);
foreach (IMenu popup in _PopupScreens)
popup.Draw();
@@ -302,6 +258,18 @@ namespace Vocaluxe.Base
return true;
}
private static void _DrawScreen(EScreens screen)
{
if (screen == EScreens.ScreenPartyDummy)
{
CFonts.PartyModeID = CParty.CurrentPartyModeID;
_Screens[(int)screen].Draw();
CFonts.PartyModeID = -1;
}
else
_Screens[(int)screen].Draw();
}
public static void FadeTo(EScreens screen)
{
if (screen == EScreens.ScreenPartyDummy)
@@ -404,9 +372,6 @@ namespace Vocaluxe.Base
CConfig.BorderTop = 0;
CConfig.BorderBottom = 0;
break;
default:
break;
}
CConfig.SaveConfig();
break;
@@ -486,8 +451,7 @@ namespace Vocaluxe.Base
if (_CurrentPopupScreen == EPopupScreens.NoPopup && diff != 0)
{
ShowPopup(EPopupScreens.PopupVolumeControl);
_VolumePopupTimer.Reset();
_VolumePopupTimer.Start();
_VolumePopupTimer.Restart();
}
CBackgroundMusic.ApplyVolume();
@@ -501,7 +465,7 @@ namespace Vocaluxe.Base
CDraw.MakeScreenShot();
else
{
if (!_Fading)
if (_Fading == null)
{
bool handled = false;
if (_CurrentPopupScreen != EPopupScreens.NoPopup)
@@ -565,12 +529,14 @@ namespace Vocaluxe.Base
bool handled = false;
if (_CurrentPopupScreen != EPopupScreens.NoPopup)
{
handled = _PopupScreens[(int)_CurrentPopupScreen].HandleMouse(mouseEvent);
if (handled && _CurrentPopupScreen == EPopupScreens.PopupVolumeControl)
_Screens[(int)_CurrentScreen].ApplyVolume();
if (handled && _CurrentPopupScreen == EPopupScreens.PopupVolumeControl)
_Screens[(int)_CurrentScreen].ApplyVolume();
}
if (!handled && !_Fading && (_Cursor.IsActive || mouseEvent.LB || mouseEvent.RB || mouseEvent.MB))
if (!handled && _Fading == null && (_Cursor.IsActive || mouseEvent.LB || mouseEvent.RB || mouseEvent.MB))
resume &= _Screens[(int)_CurrentScreen].HandleMouse(mouseEvent);
if (!eventsAvailable)
@@ -597,14 +563,14 @@ namespace Vocaluxe.Base
CDraw.MakeScreenShot();
else
{
if (!_Fading)
if (_Fading == null)
_Screens[(int)_CurrentScreen].HandleInputThemeEditor(keyEvent);
}
}
while (mouse.PollEvent(ref mouseEvent))
{
if (!_Fading)
if (_Fading == null)
_Screens[(int)_CurrentScreen].HandleMouseThemeEditor(mouseEvent);
_UpdateMousePosition(mouseEvent.X, mouseEvent.Y);
+58 -25
View File
@@ -28,6 +28,7 @@ namespace Vocaluxe.Base
private readonly string _LogFileName;
private readonly string _LogName;
private StreamWriter _LogFile;
private readonly Object _FileMutex = new Object();
public CLogFile(string fileName, string logName)
{
@@ -37,26 +38,34 @@ namespace Vocaluxe.Base
private void _Open()
{
_LogFile = new StreamWriter(Path.Combine(CSettings.DataPath, _LogFileName), false, Encoding.UTF8);
lock (_FileMutex)
{
if (_LogFile != null)
return;
_LogFile = new StreamWriter(Path.Combine(CSettings.DataPath, _LogFileName), false, Encoding.UTF8);
_LogFile.WriteLine(_LogName + " " + CSettings.GetFullVersionText() + " " + DateTime.Now);
_LogFile.WriteLine("----------------------------------------");
_LogFile.WriteLine();
_LogFile.WriteLine(_LogName + " " + CSettings.GetFullVersionText() + " " + DateTime.Now);
_LogFile.WriteLine("----------------------------------------");
_LogFile.WriteLine();
}
}
public void Close()
{
if (_LogFile == null)
return;
try
lock (_FileMutex)
{
_LogFile.Flush();
_LogFile.Close();
if (_LogFile == null)
return;
try
{
_LogFile.Flush();
_LogFile.Close();
}
catch (Exception) {}
}
catch (Exception) {}
}
public void Add(string text)
public virtual void Add(string text)
{
if (_LogFile == null)
_Open();
@@ -69,15 +78,28 @@ namespace Vocaluxe.Base
public void Dispose()
{
if (_LogFile != null)
{
_LogFile.Dispose();
_LogFile = null;
}
Close();
GC.SuppressFinalize(this);
}
}
class CErrorLogFile : CLogFile
{
private int _NumErrors;
private readonly Object _WriteMutex = new Object();
public CErrorLogFile(string fileName, string logName) : base(fileName, logName) {}
public override void Add(string errorText)
{
lock (_WriteMutex)
{
_NumErrors++;
base.Add(_NumErrors + ") " + errorText);
}
}
}
static class CLog
{
private const int _MaxBenchmarks = 10;
@@ -85,18 +107,20 @@ namespace Vocaluxe.Base
private static CLogFile _ErrorLog;
private static CLogFile _PerformanceLog;
private static CLogFile _BenchmarkLog;
private static CLogFile _DebugLog;
private static CLogFile _SongInfoLog;
private static int _NumErrors;
private static Stopwatch[] _BenchmarkTimer;
private static readonly double _NanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
public static void Init()
{
_ErrorLog = new CLogFile(CSettings.FileErrorLog, "ErrorLog");
_PerformanceLog = new CLogFile(CSettings.FilePerformanceLog, "PerformanceLog");
_BenchmarkLog = new CLogFile(CSettings.FileBenchmarkLog, "BenchmarkLog");
_ErrorLog = new CErrorLogFile(CSettings.FileErrorLog, "Error-Log");
_PerformanceLog = new CLogFile(CSettings.FilePerformanceLog, "Performance-Log");
_BenchmarkLog = new CLogFile(CSettings.FileBenchmarkLog, "Benchmark-Log");
_DebugLog = new CLogFile(CSettings.FileDebugLog, "Debug-Log");
_SongInfoLog = new CLogFile(CSettings.FileSongInfoLog, "Song-Information-Log");
_NumErrors = 0;
_BenchmarkTimer = new Stopwatch[_MaxBenchmarks];
for (int i = 0; i < _BenchmarkTimer.Length; i++)
_BenchmarkTimer[i] = new Stopwatch();
@@ -107,29 +131,38 @@ namespace Vocaluxe.Base
_ErrorLog.Close();
_PerformanceLog.Close();
_BenchmarkLog.Close();
_DebugLog.Close();
_SongInfoLog.Close();
}
#region LogError
public static void LogError(string errorText, bool show = false, bool exit = false, Exception e = null)
{
_NumErrors++;
if (show)
MessageBox.Show(errorText, CSettings.ProgramName, MessageBoxButtons.OK, MessageBoxIcon.Error);
if (e != null)
errorText += ": " + e;
_ErrorLog.Add(_NumErrors + ") " + errorText);
_ErrorLog.Add(errorText);
if (exit)
Environment.Exit(Environment.ExitCode);
}
#endregion LogError
#region LogPerformance
public static void LogDebug(string text)
{
_DebugLog.Add(String.Format("{0:HH:mm:ss.ffff}", DateTime.Now) + ":" + text);
}
public static void LogSongInfo(string text)
{
_SongInfoLog.Add(text);
}
public static void LogPerformance(string text)
{
_PerformanceLog.Add(text);
_PerformanceLog.Add("-------------------------------");
}
#endregion LogPerformance
#region LogBenchmark
public static void StartBenchmark(int benchmarkNr, string text)
+10
View File
@@ -443,6 +443,16 @@ namespace Vocaluxe.Base
{
CLog.LogError(errorText);
}
public void LogDebug(string text)
{
CLog.LogDebug(text);
}
public void LogSongInfo(string text)
{
CLog.LogSongInfo(text);
}
}
class CBfonts : IFonts
+4 -2
View File
@@ -85,6 +85,8 @@ namespace Vocaluxe.Base
public const string FilePerformanceLog = "Performance.log";
public const string FileErrorLog = "Error.log";
public const string FileBenchmarkLog = "Benchmark.log";
public const string FileDebugLog = "Debug.log";
public const string FileSongInfoLog = "SongInformation.log";
public const string SoundT440 = "440Hz.mp3";
@@ -102,7 +104,7 @@ namespace Vocaluxe.Base
#endif
Path.Combine(DataPath, FolderProfiles)
};
public static string FolderPhotos = "Photos";
public const string FolderPhotos = "Photos";
public const string FolderSongs = "Songs";
public const string FolderSounds = "Sounds";
public const string FolderLanguages = "Languages";
@@ -127,7 +129,7 @@ namespace Vocaluxe.Base
public const int NumNoteLines = 11;
public static int MouseMoveDiffMin = 2;
public const float MouseMoveOffTime = 3f;
public const int MouseMoveOffTime = 3000; //in ms
public const int MaxNumPlayer = 6;
public const int MaxScore = 10000;
+1 -3
View File
@@ -221,9 +221,7 @@ namespace Vocaluxe.Base
return;
//Calc avarage sing-count
int totalCounts = 0;
foreach (CSong song in VisibleSongs)
totalCounts += song.NumPlayedSession;
int totalCounts = VisibleSongs.Sum(song => song.NumPlayedSession);
int averageCount = totalCounts / NumSongsVisible;
foreach (CSong song in VisibleSongs)
+9 -426
View File
@@ -17,7 +17,6 @@
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using Vocaluxe.Lib.Sound;
using VocaluxeLib;
@@ -181,7 +180,7 @@ namespace Vocaluxe.Base
#endregion Playback
#region Sounds
public static int PlaySound(ESounds sound)
public static int PlaySound(ESounds sound, bool fade = true)
{
string file = Path.Combine(Environment.CurrentDirectory, CSettings.FolderSounds);
switch (sound)
@@ -189,15 +188,18 @@ namespace Vocaluxe.Base
case ESounds.T440:
file = Path.Combine(file, CSettings.SoundT440);
break;
default:
return -1;
}
if (file == "")
if (!File.Exists(file))
return -1;
int stream = Load(file);
int stream = Load(file, true);
float length = GetLength(stream);
Play(stream);
FadeAndClose(stream, 100f, length);
if (fade)
FadeAndClose(stream, 100f, length);
return stream;
}
#endregion Sounds
@@ -205,26 +207,21 @@ namespace Vocaluxe.Base
#region Record
private static IRecord _Record;
public static bool RecordInit()
public static void RecordInit()
{
switch (CConfig.RecordLib)
{
case ERecordLib.PortAudio:
_Record = new CPortAudioRecord();
break;
#if WIN
case ERecordLib.DirectSound:
_Record = new CDirectSoundRecord();
break;
#endif
// case ERecordLib.PortAudio:
default:
_Record = new CPortAudioRecord();
break;
}
return true;
}
public static void RecordCloseAll()
@@ -313,418 +310,4 @@ namespace Vocaluxe.Base
}
#endregion Record
}
class CBuffer : IDisposable
{
private const double _BaseToneFreq = 65.4064;
private const int _NumHalfTones = 47;
private readonly float[] _ToneWeigth;
private Int16[] _AnalysisBuffer = new Int16[4096];
private readonly Object _AnalysisBufferLock = new Object();
private bool _ToneValid;
private int _Tone;
private int _ToneAbs;
private double _MaxVolume;
private bool _NewSamples;
private MemoryStream _Stream; // full buffer
public CBuffer()
{
_ToneWeigth = new float[_NumHalfTones];
for (int i = 0; i < _ToneWeigth.Length; i++)
_ToneWeigth[i] = 0.99f;
_Stream = new MemoryStream();
_NewSamples = false;
}
public int NumHalfTones
{
get { return _NumHalfTones; }
}
public int ToneAbs
{
get
{
lock (_AnalysisBufferLock)
{
return _ToneAbs;
}
}
}
public int Tone
{
get
{
lock (_AnalysisBufferLock)
{
return _Tone;
}
}
set
{
lock (_AnalysisBufferLock)
{
_Tone = value;
}
}
}
public float MaxVolume
{
get
{
lock (_AnalysisBufferLock)
{
return (float)_MaxVolume;
}
}
}
public bool ToneValid
{
get
{
lock (_AnalysisBufferLock)
{
return _ToneValid;
}
}
}
public long Length
{
get { return _Stream.Length; }
}
public byte[] Buffer
{
get { return _Stream.ToArray(); }
}
public float[] ToneWeigth
{
get
{
lock (_AnalysisBufferLock)
{
return _ToneWeigth;
}
}
}
public void Reset()
{
_Stream.SetLength(0L);
_AnalysisBuffer = new Int16[_AnalysisBuffer.Length];
_ToneValid = false;
_ToneAbs = 0;
_Tone = 0;
_NewSamples = false;
}
public void Add(byte[] bytes)
{
_Stream.Write(bytes, 0, bytes.Length);
}
public void ProcessNewBuffer(byte[] buffer)
{
// apply software boost
//BoostBuffer(Buffer, BufferSize);
// voice passthrough (send data to playback-device)
//if (assigned(fVoiceStream)) then
//fVoiceStream.WriteData(Buffer, BufferSize);
lock (_AnalysisBufferLock)
{
Add(buffer);
_NewSamples = true;
}
}
public void AnalyzeBuffer()
{
if (!_NewSamples)
return;
lock (_AnalysisBufferLock)
{
int len = _AnalysisBuffer.Length * 2;
if (_Stream.Length >= len)
{
var buf = new byte[len];
_Stream.Position -= len;
_Stream.Read(buf, 0, len);
var b = new byte[2];
for (int i = 0; i < _AnalysisBuffer.Length; i++)
{
b[0] = buf[i * 2];
b[1] = buf[i * 2 + 1];
_AnalysisBuffer[i] = BitConverter.ToInt16(b, 0);
}
}
_NewSamples = false;
}
try
{
// find maximum volume
_MaxVolume = 0;
for (int i = 0; i < _AnalysisBuffer.Length / 4; i++)
{
float volume = Math.Abs((float)_AnalysisBuffer[i]) / Int16.MaxValue;
if (volume > MaxVolume)
_MaxVolume = volume;
}
_AnalyzeByAutocorrelation(_MaxVolume >= 0.02f);
}
catch (Exception) {}
}
private void _AnalyzeByAutocorrelation(bool valid)
{
if (!valid)
{
_ToneValid = false;
return;
}
const double halftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
// prepare to analyze
double maxWeight = -1.0;
double minWeight = 1.0;
int maxTone = -1;
var weigth = new float[_NumHalfTones];
// analyze halftones
// Note: at the lowest tone (~65Hz) and a buffer-size of 4096
// at 44.1 (or 48kHz) only 6 (or 5) samples are compared, this might be
// too few samples -> use a bigger buffer-size
for (int toneIndex = 0; toneIndex < _NumHalfTones; toneIndex++)
{
double curFreq = _BaseToneFreq * Math.Pow(halftoneBase, toneIndex);
double curWeight = _AnalyzeAutocorrelationFreq(curFreq);
if (curWeight > maxWeight)
{
maxWeight = curWeight;
maxTone = toneIndex;
}
if (curWeight < minWeight)
minWeight = curWeight;
weigth[toneIndex] = (float)curWeight;
}
if (maxWeight - minWeight > 0.01)
{
for (int i = 0; i < weigth.Length; i++)
_ToneWeigth[i] = weigth[i];
_ToneAbs = maxTone;
_Tone = maxTone % 12;
_ToneValid = true;
}
else
_ToneValid = false;
}
private double _AnalyzeAutocorrelationFreq(double freq)
{
int sampleIndex = 0; // index of sample to analyze
var samplesPerPeriod = (int)Math.Round(44100.0 / freq); // samples in one period
int correlatingSampleIndex = sampleIndex + samplesPerPeriod; // index of sample one period ahead
double accumDist = 0.0; // accumulated distances
// compare correlating samples
while (correlatingSampleIndex < _AnalysisBuffer.Length)
{
// calc distance (correlation: 1-dist) to corresponding sample in next period
// distance (0=equal .. 1=totally different) between correlated samples
double dist = Math.Abs((double)_AnalysisBuffer[sampleIndex] - _AnalysisBuffer[correlatingSampleIndex]) / Int16.MaxValue;
accumDist += dist;
sampleIndex++;
correlatingSampleIndex++;
}
return 1 - accumDist / _AnalysisBuffer.Length;
}
public void Dispose()
{
if (_Stream != null)
{
_Stream.Dispose();
_Stream = null;
}
GC.SuppressFinalize(this);
}
}
class CSyncTimer
{
private readonly CPt1 _ExternTime;
private readonly Stopwatch _Timer;
private float _SetValue;
public float Time
{
get
{
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
return _SetValue + dt;
}
set
{
_ExternTime.Time = value;
_SetValue = value;
_Timer.Reset();
_Timer.Start();
}
}
public CSyncTimer(float currentTime, float k, float t)
{
_ExternTime = new CPt1(currentTime, k, t);
_Timer = new Stopwatch();
_SetValue = currentTime;
}
public float Update(float newTime)
{
float et = _ExternTime.Update(newTime);
float dt = Time;
float diff = et - dt;
if (Math.Abs(diff) > 0.05f)
{
_Timer.Reset();
_Timer.Start();
_SetValue = dt + diff;
dt = _SetValue;
//Console.WriteLine("DRIFTED!!! " + diff.ToString());
}
else
{
if (diff > 0.01f)
_SetValue += 0.000025f;
if (diff < -0.01f)
_SetValue -= 0.000025f;
}
//Console.WriteLine(diff.ToString());
return dt;
}
public void Pause()
{
_ExternTime.Pause();
_Timer.Stop();
}
public void Resume()
{
_ExternTime.Resume();
_Timer.Start();
}
}
class CPt1
{
private float _CurrentTime;
private float _OldTime;
private readonly Stopwatch _Timer;
private readonly float _K;
private readonly float _T;
public float Time
{
get
{
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
return _CurrentTime + dt;
}
set
{
if (value < 0f)
return;
_CurrentTime = value;
_OldTime = value;
_Timer.Reset();
_Timer.Start();
}
}
public CPt1(float currentTime, float k, float t)
{
_CurrentTime = currentTime;
_OldTime = currentTime;
_Timer = new Stopwatch();
_K = k;
_T = t;
}
public float Update(float newTime)
{
_Timer.Stop();
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
float ts = 0f;
if (dt > 0)
ts = 1 / (_T / dt + 1);
_CurrentTime = ts * (_K * newTime - _OldTime) + _OldTime;
_OldTime = _CurrentTime;
_Timer.Reset();
_Timer.Start();
return _CurrentTime;
}
public void Pause()
{
_Timer.Stop();
}
public void Resume()
{
_Timer.Start();
}
}
}
+2 -12
View File
@@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using Vocaluxe.Base.Fonts;
@@ -789,14 +788,8 @@ namespace Vocaluxe.Base
public static SColorF GetPlayerColor(int playerNr)
{
var color = new SColorF(1f, 1f, 1f, 1f);
int skinIndex = GetSkinIndex(-1);
if (_Skins[skinIndex].ThemeColors.Player.Length < playerNr)
return color;
return _Skins[skinIndex].ThemeColors.Player[playerNr - 1];
bool dummy;
return GetPlayerColor(playerNr, out dummy);
}
public static SColorF GetPlayerColor(string playerNrString)
@@ -823,9 +816,6 @@ namespace Vocaluxe.Base
{
success = false;
if (_Skins[skinIndex].PartyModeID != -1)
skinIndex = GetSkinIndex(-1);
if (_Skins[skinIndex].ThemeColors.Player.Length < playerNr || playerNr < 1)
return new SColorF(1f, 1f, 1f, 1f);
+9
View File
@@ -135,6 +135,7 @@ namespace Vocaluxe.Base
{
_VideoStream = CVideo.Load(CTheme.GetVideoFilePath(videoName, -1));
_Loaded = true;
CVideo.Pause(_VideoStream);
}
public void Start()
@@ -143,15 +144,18 @@ namespace Vocaluxe.Base
_Finished = false;
//CVideo.VdSkip(_VideoStream, 0f, 0f);
_VideoTimer.Start();
CVideo.Resume(_VideoStream);
}
public void Pause()
{
CVideo.Pause(_VideoStream);
_VideoTimer.Stop();
}
public void Resume()
{
CVideo.Resume(_VideoStream);
_VideoTimer.Start();
}
@@ -175,6 +179,9 @@ namespace Vocaluxe.Base
public void PreLoad()
{
bool paused = _VideoTimer.IsRunning;
if (paused)
CVideo.Resume(_VideoStream);
float videoTime = 0f;
while (_VideoTexture == null && videoTime < 1f)
{
@@ -182,6 +189,8 @@ namespace Vocaluxe.Base
CVideo.GetFrame(_VideoStream, ref _VideoTexture, 0, out dummy);
videoTime += 0.05f;
}
if (paused)
CVideo.Pause(_VideoStream);
}
public void Close()
+1 -2
View File
@@ -96,9 +96,8 @@ namespace Vocaluxe.Base.Server
var stream = new MemoryStream();
stream.Write(cmd, 0, cmd.Length);
byte[] data;
string json = JsonConvert.SerializeObject(obj);
data = _Encoder.GetBytes(json);
byte[] data = _Encoder.GetBytes(json);
stream.Write(data, 0, data.Length);
return stream.ToArray();
}
+7 -8
View File
@@ -26,7 +26,6 @@ using ServerLib;
using Vocaluxe.Lib.Input;
using Vocaluxe.Lib.Playlist;
using VocaluxeLib;
using VocaluxeLib.Draw;
using VocaluxeLib.Menu;
using VocaluxeLib.Profile;
using VocaluxeLib.Songs;
@@ -314,7 +313,7 @@ namespace Vocaluxe.Base.Server
#endregion
#region photo
private static List<string> photosOfThisRound = new List<string>();
private static readonly List<string> _PhotosOfThisRound = new List<string>();
private static bool _SendPhoto(SPhotoData photoData)
{
@@ -325,17 +324,17 @@ namespace Vocaluxe.Base.Server
string filePath = _SaveImage(photoData.Photo, name, CSettings.FolderPhotos);
if (!string.IsNullOrEmpty(filePath))
{
photosOfThisRound.Add(filePath);
_PhotosOfThisRound.Add(filePath);
return true;
}
return false;
}
internal static string[] getPhotosOfThisRound()
internal static string[] GetPhotosOfThisRound()
{
string[] result = photosOfThisRound.ToArray();
photosOfThisRound.Clear();
string[] result = _PhotosOfThisRound.ToArray();
_PhotosOfThisRound.Clear();
return result;
}
#endregion
@@ -583,11 +582,11 @@ namespace Vocaluxe.Base.Server
return false;
}
byte[] salt = profile.PasswordSalt;
//byte[] salt = profile.PasswordSalt;
return hashedPassword.SequenceEqual(profile.PasswordHash);
}
private static byte[] _GetPassowordSalt(int profileId)
private static byte[] _GetPasswordSalt(int profileId)
{
CProfile profile = CProfiles.GetProfile(profileId);
if (profile == null)
-4
View File
@@ -16,12 +16,8 @@
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Security;
using System.Text;
using Microsoft.Win32;
using Vocaluxe.Base;
+6 -6
View File
@@ -161,25 +161,25 @@ namespace Vocaluxe.Lib.Input
public static int ReadTimeout(IntPtr device, ref byte[] data, int length, int milliseconds)
{
IntPtr dataPtr = Marshal.AllocHGlobal(length);
int result;
int bytesRead;
try
{
result = hid_read_timeout(device, dataPtr, length, milliseconds);
bytesRead = hid_read_timeout(device, dataPtr, length, milliseconds);
}
catch (Exception e)
{
result = -1;
bytesRead = -1;
CLog.LogError("Error CHIDAPI.ReadTimeout(): " + e);
}
if (result != -1)
Marshal.Copy(dataPtr, data, 0, result);
if (bytesRead != -1)
Marshal.Copy(dataPtr, data, 0, bytesRead);
else
data = null;
Marshal.FreeHGlobal(dataPtr);
return result;
return bytesRead;
}
[DllImport(_HIDApiDll, ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, EntryPoint = "hid_read", CharSet = CharSet.Unicode)]
+3 -14
View File
@@ -25,7 +25,7 @@ using VocaluxeLib;
namespace Vocaluxe.Lib.Input.WiiMote
{
class CWiiMote : IController, IDisposable
class CWiiMote : IController
{
private CWiiMoteLib _WiiMote;
@@ -54,7 +54,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
_RumbleTimer = new CRumbleTimer();
_Gesture = new CGesture();
_HandlerThread = new Thread(_MainLoop) {Priority = ThreadPriority.BelowNormal};
_HandlerThread = new Thread(_MainLoop) {Name = "WiiMote", Priority = ThreadPriority.BelowNormal};
_KeysPool = new List<SKeyEvent>();
_CurrentKeysPool = new List<SKeyEvent>();
@@ -151,8 +151,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
if (startRumble)
_WiiMote.SetRumble(true);
if (stopRumble)
else if (stopRumble)
_WiiMote.SetRumble(false);
}
}
@@ -314,15 +313,5 @@ namespace Vocaluxe.Lib.Input.WiiMote
_MousePool.Clear();
}
}
public void Dispose()
{
if (_WiiMote != null)
{
_WiiMote.Dispose();
_WiiMote = null;
}
GC.SuppressFinalize(this);
}
}
}
+59 -104
View File
@@ -137,7 +137,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
}
#endregion Events
public sealed class CWiiMoteLib : IDisposable
public sealed class CWiiMoteLib
{
// ReSharper disable InconsistentNaming
private const ushort _VID = 0x057e;
@@ -178,8 +178,7 @@ namespace Vocaluxe.Lib.Input.WiiMote
private int _Address;
private short _Size;
private readonly Thread _Reader;
private bool _Active;
private Thread _Reader;
private readonly bool _Error;
public bool Connected { get; private set; }
@@ -191,72 +190,63 @@ namespace Vocaluxe.Lib.Input.WiiMote
#region Interface
public CWiiMoteLib()
{
Connected = false;
_Active = true;
_Error = false;
_Reader = new Thread(_ReaderLoop);
_Reader.Start();
if (!CHIDApi.Init())
{
CLog.LogError("WiiMoteLib: Can't initialize HID API");
const string msg = "Please install the Visual C++ Redistributable Packages 2008!";
CLog.LogError(msg);
CLog.LogError("Please install the Visual C++ Redistributable Packages 2008!");
_Active = false;
_Error = true;
}
}
~CWiiMoteLib()
{
Dispose(false);
Disconnect();
//Wait for thread to finish (if any)
_WaitForReader();
CHIDApi.Exit();
_ReadDone.Dispose();
}
private bool _TryConnect(ushort pid)
private void _StartReader()
{
bool connected = CHIDApi.Open(_VID, pid, out _Handle);
if (connected)
_Reader = new Thread(_ReaderLoop) {Name = "WiiMoteLib"};
_Reader.Start();
}
private void _WaitForReader()
{
if (_Reader == null)
return;
_Reader.Join();
_Reader = null;
}
private void _TryConnect(ushort pid)
{
//We might have had a reader thread, that is not finished yet, so let it finish and close it's handle first or it will close the new one
_WaitForReader();
Connected = CHIDApi.Open(_VID, pid, out _Handle);
if (Connected)
{
connected = _ReadCalibration();
if (!connected)
CHIDApi.Close(_Handle);
_StartReader();
if (!_ReadCalibration())
Connected = false;
}
return connected;
}
public bool Connect()
{
Connected = false;
if (Connected)
return true;
if (_Error)
return false;
//Try WiiMotion
Connected = CHIDApi.Open(_VID, _PID, out _Handle);
if (Connected)
{
Connected = _ReadCalibration();
if (!Connected)
CHIDApi.Close(_Handle);
}
else
CHIDApi.Close(_Handle);
if (Connected)
return true;
//Try WiiMotion Plus
Connected = CHIDApi.Open(_VID, _PIDPlus, out _Handle);
if (Connected)
{
Connected = _ReadCalibration();
if (!Connected)
CHIDApi.Close(_Handle);
}
else
CHIDApi.Close(_Handle);
_TryConnect(_PID); //Try WiiMotion
if (!Connected)
_TryConnect(_PIDPlus); //Try WiiMotion Plus
return Connected;
}
@@ -264,8 +254,6 @@ namespace Vocaluxe.Lib.Input.WiiMote
public void Disconnect()
{
Connected = false;
_Active = false;
CHIDApi.Exit();
}
public void SetReportType(EInputReport type, EIRSensitivity irSensitivity, bool continuous)
@@ -328,68 +316,54 @@ namespace Vocaluxe.Lib.Input.WiiMote
#region Private stuff
private void _ReaderLoop()
{
while (_Active)
var buff = new byte[_ReportLength];
while (Connected)
{
Thread.Sleep(5);
if (_Handle != IntPtr.Zero && Connected)
int bytesRead;
try
{
var buff = new byte[_ReportLength];
try
bytesRead = CHIDApi.ReadTimeout(_Handle, ref buff, _ReportLength, 400);
if (bytesRead == -1)
{
CHIDApi.ReadTimeout(_Handle, ref buff, _ReportLength, 200);
}
catch (Exception e)
{
CLog.LogError("(WiiMoteLib) Error reading from device: " + e);
}
if (_ParseInputReport(buff))
{
if (WiiMoteChanged != null)
WiiMoteChanged(this, new CWiiMoteChangedEventArgs(_WiiMoteState));
Connected = false; //Disconnected
break;
}
}
catch (Exception e)
{
CLog.LogError("(WiiMoteLib) Error reading from device: " + e);
Connected = false;
break;
}
if (bytesRead > 0 && _ParseInputReport(buff))
{
if (WiiMoteChanged != null)
WiiMoteChanged(this, new CWiiMoteChangedEventArgs(_WiiMoteState));
}
Thread.Sleep(5);
}
CHIDApi.Close(_Handle);
}
private bool _ParseInputReport(byte[] buff)
{
if (buff == null)
{
Connected = false;
return false;
}
var type = (EInputReport)buff[0];
switch (type)
{
case EInputReport.Buttons:
_ParseButtons(buff);
break;
case EInputReport.ButtonsAccel:
_ParseButtons(buff);
_ParseAccel(buff);
break;
case EInputReport.IRAccel:
_ParseButtons(buff);
_ParseAccel(buff);
_ParseIR(buff);
break;
case EInputReport.ButtonsExtension:
_ParseButtons(buff);
break;
case EInputReport.ButtonsAccel:
case EInputReport.ExtensionAccel:
_ParseButtons(buff);
_ParseAccel(buff);
break;
case EInputReport.IRAccel:
case EInputReport.IRExtensionAccel:
_ParseButtons(buff);
_ParseAccel(buff);
@@ -693,24 +667,5 @@ namespace Vocaluxe.Lib.Input.WiiMote
Thread.Sleep(100);
}
#endregion Private stuff
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// ReSharper disable InconsistentNaming
private void Dispose(bool disposing)
// ReSharper restore InconsistentNaming
{
if (disposing)
{
Disconnect();
_ReadDone.Close();
}
}
#endregion
}
}
-1
View File
@@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using Vocaluxe.Base;
using VocaluxeLib;
+209
View File
@@ -0,0 +1,209 @@
using System;
using System.IO;
namespace Vocaluxe.Lib.Sound
{
class CBuffer : IDisposable
{
private const double _BaseToneFreq = 65.4064;
public const int NumHalfTones = 17;
private const int _AnalysisBufLen = 4096;
private const int _AnalysisByteBufLen = _AnalysisBufLen * 2;
private readonly Int16[] _AnalysisBuffer = new Int16[_AnalysisBufLen];
private readonly byte[] _AnalysisByteBuffer = new byte[_AnalysisByteBufLen]; //tmp buffer (stream->tmpBuffer->(Int16)AnalysisBuffer)
private static readonly int[] _SamplesPerPeriodPerTone = new int[NumHalfTones]; //Precalculated table holding sample# per period for each tone
private readonly float[] _TmpWeight = new float[NumHalfTones]; //tmp buffer for weights (gets copied to ToneWeight when checked)
private double _MaxVolume;
private bool _NewSamples;
private MemoryStream _Stream = new MemoryStream(); // full buffer
public CBuffer()
{
ToneWeigth = new float[NumHalfTones];
for (int i = 0; i < ToneWeigth.Length; i++)
ToneWeigth[i] = 0.99f;
}
static CBuffer()
{
const double halftoneBase = 1.05946309436; // 2^(1/12) -> HalftoneBase^12 = 2 (one octave)
//Init Array to avoid costly calculations
for (int toneIndex = 0; toneIndex < NumHalfTones; toneIndex++)
{
double freq = _BaseToneFreq * Math.Pow(halftoneBase, toneIndex);
_SamplesPerPeriodPerTone[toneIndex] = (int)Math.Round(44100.0 / freq); // samples in one period
}
}
public int ToneAbs { get; private set; }
public int Tone { get; set; }
public float MaxVolume
{
get { return (float)_MaxVolume; }
}
public bool ToneValid { get; private set; }
public float[] ToneWeigth { get; private set; }
public void Reset()
{
lock (_Stream)
{
_Stream.SetLength(0L);
_NewSamples = false;
}
ToneValid = false;
ToneAbs = 0;
Tone = 0;
}
private void _Add(byte[] bytes)
{
_Stream.Write(bytes, 0, bytes.Length);
}
public void ProcessNewBuffer(byte[] buffer)
{
// apply software boost
//BoostBuffer(Buffer, BufferSize);
// voice passthrough (send data to playback-device)
//if (assigned(fVoiceStream)) then
//fVoiceStream.WriteData(Buffer, BufferSize);
lock (_Stream)
{
_Add(buffer);
_NewSamples = true;
}
}
public void AnalyzeBuffer()
{
if (!_NewSamples)
return;
lock (_Stream)
{
if (_Stream.Length >= _AnalysisByteBufLen)
{
_Stream.Position -= _AnalysisByteBufLen;
_Stream.Read(_AnalysisByteBuffer, 0, _AnalysisByteBufLen);
}
_NewSamples = false;
}
for (int i = 0; i < _AnalysisBufLen; i++)
_AnalysisBuffer[i] = BitConverter.ToInt16(_AnalysisByteBuffer, i * 2);
try
{
// find maximum volume
_FindMaxVolume();
if (MaxVolume >= 0.02)
_AnalyzeByAutocorrelation();
else
ToneValid = false;
}
catch (Exception) {}
}
private void _FindMaxVolume()
{
short maxVolume = 0;
for (int i = 0; i < _AnalysisBuffer.Length / 4; i++)
{
short volume = _AnalysisBuffer[i];
if (volume < 0)
{
if (volume == Int16.MinValue)
{
maxVolume = Int16.MaxValue;
break;
}
volume = (short)-volume;
}
if (volume > maxVolume)
maxVolume = volume;
}
_MaxVolume = (double)maxVolume / Int16.MaxValue;
}
private void _AnalyzeByAutocorrelation()
{
// prepare to analyze
double maxWeight = -1.0;
double minWeight = 1.0;
int maxTone = -1;
// analyze halftones
// Note: at the lowest tone (~65Hz) and a buffer-size of 4096
// at 44.1 (or 48kHz) only 6 (or 5) samples are compared, this might be
// too few samples -> use a bigger buffer-size
for (int toneIndex = 0; toneIndex < NumHalfTones; toneIndex++)
{
double curWeight = _AnalyzeAutocorrelationTone(toneIndex);
if (curWeight > maxWeight)
{
maxWeight = curWeight;
maxTone = toneIndex;
}
if (curWeight < minWeight)
minWeight = curWeight;
_TmpWeight[toneIndex] = (float)curWeight;
}
if (maxWeight - minWeight > 0.01)
{
Array.Copy(_TmpWeight, ToneWeigth, NumHalfTones);
ToneAbs = maxTone;
Tone = maxTone % 12;
ToneValid = true;
}
else
ToneValid = false;
}
private double _AnalyzeAutocorrelationTone(int tone)
{
int samplesPerPeriod = _SamplesPerPeriodPerTone[tone]; // samples in one period
int accumDist = 0; // accumulated distances
// compare correlating samples
int sampleIndex = 0; // index of sample to analyze
// Start value= index of sample one period ahead
for (int correlatingSampleIndex = sampleIndex + samplesPerPeriod; correlatingSampleIndex < _AnalysisBufLen; correlatingSampleIndex++, sampleIndex++)
{
// calc distance (correlation: 1-dist/IntMax) to corresponding sample in next period
// distance (0=equal .. IntMax=totally different) between correlated samples
int dist = Math.Abs(_AnalysisBuffer[sampleIndex] - _AnalysisBuffer[correlatingSampleIndex]);
accumDist += dist;
}
return 1.0 - (double)accumDist / Int16.MaxValue / _AnalysisBufLen;
}
public void Dispose()
{
if (_Stream != null)
{
_Stream.Dispose();
_Stream = null;
}
GC.SuppressFinalize(this);
}
}
}
+102
View File
@@ -0,0 +1,102 @@
using System.Diagnostics;
using Vocaluxe.Base;
namespace Vocaluxe.Lib.Sound
{
class CDelayTest
{
private struct SDelayChannel
{
public int Channel;
public bool Finished;
}
private const float _MaxDelayTime = 1000;
public bool Running { get; private set; }
private readonly Stopwatch _Timer = new Stopwatch();
private int _Stream = -1;
private readonly SDelayChannel[] _DelaysChannel;
public readonly int[] Delays;
public readonly int NumChannels;
public CDelayTest(int numChannels)
{
NumChannels = numChannels;
_DelaysChannel = new SDelayChannel[NumChannels];
Delays = new int[NumChannels];
}
public void Start(int[] channels)
{
if (Running)
return;
Reset();
for (int i = 0; i < _DelaysChannel.Length; i++)
{
if (i < channels.Length)
{
_DelaysChannel[i].Finished = false;
_DelaysChannel[i].Channel = channels[i];
}
else
_DelaysChannel[i].Finished = true;
}
_Stream = CSound.PlaySound(ESounds.T440, false);
Running = true;
}
public void Reset()
{
Running = false;
for (int i = 0; i < _DelaysChannel.Length; i++)
Delays[i] = 0;
_CloseStream();
}
private void _CloseStream()
{
if (_Stream != -1)
{
CSound.Close(_Stream);
_Stream = -1;
}
}
public void Update()
{
if (!Running)
return;
if (!_Timer.IsRunning)
{
if (CSound.GetPosition(_Stream) > 0f)
_Timer.Restart();
}
if (!_Timer.IsRunning)
return;
bool isActive = false;
if (_Timer.ElapsedMilliseconds <= _MaxDelayTime)
{
for (int i = 0; i < _DelaysChannel.Length; i++)
{
if (_DelaysChannel[i].Channel < 0 || _DelaysChannel[i].Finished)
continue;
if (CSound.RecordGetMaxVolume(_DelaysChannel[i].Channel) > 0.1f && CSound.RecordGetTone(_DelaysChannel[i].Channel) == 9)
{
Delays[i] = (int)_Timer.ElapsedMilliseconds;
_DelaysChannel[i].Finished = true;
}
else
isActive = true;
}
}
if (!isActive)
{
Running = false;
_CloseStream();
_Timer.Stop();
}
}
}
}
+2 -2
View File
@@ -192,7 +192,7 @@ namespace Vocaluxe.Lib.Sound
if (!_Initialized)
return 0;
return _Buffer[player].NumHalfTones;
return CBuffer.NumHalfTones;
}
public float[] ToneWeigth(int player)
@@ -326,7 +326,7 @@ namespace Vocaluxe.Lib.Sound
for (int i = 0; i < _Notifications.Count; i++)
_WaitHandles[i] = _Notifications[i].Event;
_CaptureThread = new Thread(_DoCapture) {IsBackground = true};
_CaptureThread = new Thread(_DoCapture) {Name = "DirectSoundCapture", IsBackground = true};
_Running = true;
_CaptureThread.Start();
+62 -47
View File
@@ -20,8 +20,8 @@ using System.Collections.Generic;
using Gst;
using GLib;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Vocaluxe.Base;
using VocaluxeLib;
using Thread = System.Threading.Thread;
namespace Vocaluxe.Lib.Sound
@@ -37,10 +37,10 @@ namespace Vocaluxe.Lib.Sound
public bool Init()
{
#if ARCH_X86
string path = ".\\x86\\gstreamer";
const string path = ".\\x86\\gstreamer";
#endif
#if ARCH_X64
string path = ".\\x64\\gstreamer";
const string path = ".\\x64\\gstreamer";
#endif
SetDllDirectory(path);
Application.Init();
@@ -213,21 +213,16 @@ namespace Vocaluxe.Lib.Sound
private class CGstreamerSharpAudioStream
{
private readonly Element _Element;
private Element _Element;
private bool _Loop;
public volatile bool Closed;
public volatile bool Closed = true;
public volatile bool Finished;
private bool _Fading;
private bool _CloseStreamAfterFade;
private bool _PauseStreamAfterFade;
private bool _StopStreamAfterFade;
private readonly Stopwatch _FadeTimer = new Stopwatch();
private float _FadeTime;
private float _FadeVolume;
private float _Volume = 100f;
private CFading _Fading;
private EStreamAction _AfterFadeAction;
private float _Volume = 1f;
private float _MaxVolume = 100f;
private float _MaxVolume = 1f;
private volatile float _Duration = -1f;
private volatile float _Position;
@@ -240,7 +235,10 @@ namespace Vocaluxe.Lib.Sound
var audioSinkBin = new Bin("Audiosink");
if (convert == null || audiosink == null)
{
CLog.LogError("Could not create pipeline");
return;
}
audioSinkBin.Add(convert);
audioSinkBin.Add(audiosink);
@@ -249,21 +247,35 @@ namespace Vocaluxe.Lib.Sound
GhostPad ghostpad = new GhostPad("sink", pad);
if (pad == null)
{
CLog.LogError("Could not create pads");
return;
}
if (!ghostpad.SetActive(true))
{
CLog.LogError("Could not link pads");
return;
}
if (!audioSinkBin.AddPad(ghostpad))
{
CLog.LogError("Could not add pad");
return;
}
_Element = ElementFactory.Make("playbin", "playbin");
if (_Element == null)
{
CLog.LogError("Could not create playbin");
return;
}
_Element["audio-sink"] = audioSinkBin;
_Element["flags"] = 1 << 1;
_Element["uri"] = new Uri(media).AbsoluteUri;
_Element.SetState(State.Paused);
Closed = false; //Enable stream
// Passing CLOCK_TIME_NONE here causes the pipeline to block for a long time so with
// prescan enabled the pipeline will wait 500ms for stream to initialize and then continue
// if it takes more than 500ms, duration queries will be performed asynchronously
@@ -285,8 +297,10 @@ namespace Vocaluxe.Lib.Sound
if (_Loop)
Position = 0;
else
{
Finished = true;
Close();
Close();
}
break;
case MessageType.Error:
GException error;
@@ -295,7 +309,8 @@ namespace Vocaluxe.Lib.Sound
CLog.LogError("Gstreamer error: message" + error.Message + ", code" + error.Code + " ,debug information" + debug);
break;
case MessageType.DurationChanged:
_UpdateDuration();
if (!_QueryingDuration)
_UpdateDuration();
break;
}
msg.Unref();
@@ -307,7 +322,7 @@ namespace Vocaluxe.Lib.Sound
{
Closed = true;
Finished = true;
var t = new Thread(_TerminateStream);
var t = new Thread(_TerminateStream) {Name = "GSt Terminate"};
t.Start();
}
}
@@ -318,6 +333,7 @@ namespace Vocaluxe.Lib.Sound
{
_Element.SetState(State.Null);
_Element.Dispose();
_Element = null;
}
}
@@ -337,47 +353,45 @@ namespace Vocaluxe.Lib.Sound
public void Fade(float targetVolume, float seconds)
{
_Fading = true;
_FadeTimer.Restart();
_FadeTime = seconds;
_FadeVolume = targetVolume;
_Fading = new CFading(_Volume, targetVolume, seconds);
_AfterFadeAction = EStreamAction.Nothing;
}
public void FadeAndPause(float targetVolume, float seconds)
{
Fade(targetVolume, seconds);
_PauseStreamAfterFade = true;
_AfterFadeAction = EStreamAction.Pause;
}
public void FadeAndClose(float targetVolume, float seconds)
{
Fade(targetVolume, seconds);
_CloseStreamAfterFade = true;
_AfterFadeAction = EStreamAction.Close;
}
public void FadeAndStop(float targetVolume, float seconds)
{
Fade(targetVolume, seconds);
_StopStreamAfterFade = true;
_AfterFadeAction = EStreamAction.Stop;
}
public float Volume
{
get { return _Element != null ? (float)(double)_Element["volume"] : 0; }
get { return _Volume * 100f; }
set
{
_Volume = value;
_Volume = value / 100f;
if (_Element != null)
_Element["volume"] = ((value / 100d) * (_MaxVolume / 100d));
_Element["volume"] = (_Volume * _MaxVolume);
}
}
public float MaxVolume
{
get { return _MaxVolume; }
get { return _MaxVolume * 100f; }
set
{
_MaxVolume = value;
_MaxVolume = value / 100f;
Volume = _Volume;
}
}
@@ -388,7 +402,8 @@ namespace Vocaluxe.Lib.Sound
{
if (_Duration < 0 && !_QueryingDuration)
{
var t = new Thread(_UpdateDuration);
_QueryingDuration = true; // Set this to avoid race conditions
var t = new Thread(_UpdateDuration) {Name = "GSt Update Duration"};
t.Start();
}
return _Duration > 0 ? _Duration : -1;
@@ -438,25 +453,25 @@ namespace Vocaluxe.Lib.Sound
while (_Element != null && _Element.Bus != null && _Element.Bus.HavePending())
_OnMessage(_Element.Bus.Pop());
if (_Fading)
if (_Fading != null)
{
if (_FadeTimer.ElapsedMilliseconds < (_FadeTime * 1000f))
Volume = ((_FadeTimer.ElapsedMilliseconds) / (_FadeTime * 1000f)) * _FadeVolume;
else
bool finished;
Volume = _Fading.GetValue(out finished);
if (finished)
{
Volume = _FadeVolume;
if (_CloseStreamAfterFade)
Close();
if (_PauseStreamAfterFade)
Paused = true;
if (_StopStreamAfterFade)
Stop();
_CloseStreamAfterFade = false;
_PauseStreamAfterFade = false;
_StopStreamAfterFade = false;
_Fading = false;
_FadeTimer.Reset();
switch (_AfterFadeAction)
{
case EStreamAction.Pause:
Paused = true;
break;
case EStreamAction.Stop:
Stop();
break;
case EStreamAction.Close:
Close();
break;
}
_Fading = null;
}
}
}
+24 -32
View File
@@ -24,6 +24,7 @@ using System.IO;
using System.Threading;
using Vocaluxe.Base;
using Vocaluxe.Lib.Sound.Decoder;
using VocaluxeLib;
namespace Vocaluxe.Lib.Sound
{
@@ -370,14 +371,8 @@ namespace Vocaluxe.Lib.Sound
private float _Volume = 1f;
private float _VolumeMax = 1f;
private readonly Stopwatch _FadeTimer = new Stopwatch();
private float _FadeTime;
private float _TargetVolume = 1f;
private float _StartVolume = 1f;
private bool _CloseStreamAfterFade;
private bool _PauseStreamAfterFade;
private bool _Fading;
private EStreamAction _AfterFadeAction;
private CFading _Fading;
private readonly Stopwatch _Timer = new Stopwatch();
@@ -416,7 +411,7 @@ namespace Vocaluxe.Lib.Sound
public COpenAlStream()
{
_Initialized = false;
_DecoderThread = new Thread(_Execute);
_DecoderThread = new Thread(_Execute) {Name = "OpenAL Decode"};
}
public void Free(Closeproc closeProc, int streamID, Object closeMutex)
@@ -519,33 +514,28 @@ namespace Vocaluxe.Lib.Sound
public void Fade(float targetVolume, float fadeTime)
{
_Fading = true;
_FadeTimer.Stop();
_FadeTimer.Reset();
_StartVolume = _Volume;
_TargetVolume = targetVolume / 100f;
_FadeTime = fadeTime;
_FadeTimer.Start();
_Fading = new CFading(_Volume, targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Nothing;
}
public void FadeAndPause(float targetVolume, float fadeTime)
{
_PauseStreamAfterFade = true;
Fade(targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Pause;
}
public void FadeAndStop(float targetVolume, float fadeTime, Closeproc closeProc, int streamID)
{
_Closeproc = closeProc;
_StreamID = streamID;
_CloseStreamAfterFade = true;
Fade(targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Stop;
}
public void Play()
{
Paused = false;
_PauseStreamAfterFade = false;
_AfterFadeAction = EStreamAction.Nothing;
AL.SourcePlay(_Source);
}
@@ -745,21 +735,23 @@ namespace Vocaluxe.Lib.Sound
private void _Update()
{
if (_Fading)
if (_Fading != null)
{
if (_FadeTimer.ElapsedMilliseconds / 1000f < _FadeTime)
_Volume = _StartVolume + (_TargetVolume - _StartVolume) * ((_FadeTimer.ElapsedMilliseconds / 1000f) / _FadeTime);
else
bool finished;
_Volume = _Fading.GetValue(out finished);
if (finished)
{
_Volume = _TargetVolume;
_FadeTimer.Stop();
_Fading = false;
if (_CloseStreamAfterFade)
_Terminated = true;
if (_PauseStreamAfterFade)
Paused = true;
switch (_AfterFadeAction)
{
case EStreamAction.Close:
case EStreamAction.Stop:
_Terminated = true;
break;
case EStreamAction.Pause:
Paused = true;
break;
}
_Fading = null;
}
}
}
+27 -44
View File
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@@ -25,6 +24,7 @@ using System.Threading;
using Vocaluxe.Base;
using Vocaluxe.Lib.Sound.Decoder;
using Vocaluxe.Lib.Sound.PortAudio;
using VocaluxeLib;
namespace Vocaluxe.Lib.Sound
{
@@ -351,15 +351,8 @@ namespace Vocaluxe.Lib.Sound
private float _Volume = 1f;
private float _VolumeMax = 1f;
private readonly Stopwatch _FadeTimer = new Stopwatch();
private float _FadeTime;
private float _TargetVolume = 1f;
private float _StartVolume = 1f;
private bool _CloseStreamAfterFade;
private bool _PauseStreamAfterFade;
private bool _StopStreamAfterFade;
private bool _Fading;
private EStreamAction _AfterFadeAction;
private CFading _Fading;
private static CPortAudio.SPaHostApiInfo _ApiInfo;
private static CPortAudio.SPaDeviceInfo _OutputDeviceInfo;
@@ -401,7 +394,7 @@ namespace Vocaluxe.Lib.Sound
public CPortAudioStream()
{
_SyncTimer = new CSyncTimer(0f, 1f, 0.02f);
_DecoderThread = new Thread(_Execute);
_DecoderThread = new Thread(_Execute) {Name = "PortAudio Decode"};
}
~CPortAudioStream()
@@ -507,19 +500,12 @@ namespace Vocaluxe.Lib.Sound
public void Fade(float targetVolume, float fadeTime)
{
_Fading = true;
_FadeTimer.Stop();
_FadeTimer.Reset();
_StartVolume = _Volume;
_TargetVolume = targetVolume / 100f;
_FadeTime = fadeTime;
_FadeTimer.Start();
_Fading = new CFading(_Volume, targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Nothing;
}
public void FadeAndPause(float targetVolume, float fadeTime)
{
_PauseStreamAfterFade = true;
Fade(targetVolume, fadeTime);
}
@@ -527,25 +513,22 @@ namespace Vocaluxe.Lib.Sound
{
_Closeproc = closeProc;
_StreamID = streamID;
_CloseStreamAfterFade = true;
Fade(targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Close;
}
public void FadeAndStop(float targetVolume, float fadeTime, Closeproc closeProc, int streamID)
{
_Closeproc = closeProc;
_StreamID = streamID;
_StopStreamAfterFade = true;
Fade(targetVolume, fadeTime);
_AfterFadeAction = EStreamAction.Stop;
}
public void Play()
{
Paused = false;
_PauseStreamAfterFade = false;
_StopStreamAfterFade = false;
_AfterFadeAction = EStreamAction.Nothing;
lock (_Mutex)
{
_ErrorCheck("StartStream", CPortAudio.Pa_StartStream(_Ptr));
@@ -665,7 +648,7 @@ namespace Vocaluxe.Lib.Sound
return -1;
}
public bool Skip(float time)
public void Skip(float time)
{
lock (_LockSyncSignals)
{
@@ -673,8 +656,6 @@ namespace Vocaluxe.Lib.Sound
_SetSkip = true;
_Waiting = true;
}
return true;
}
#region Threading
@@ -929,23 +910,25 @@ namespace Vocaluxe.Lib.Sound
private void _Update()
{
if (_Fading)
if (_Fading != null)
{
if (_FadeTimer.ElapsedMilliseconds / 1000f < _FadeTime)
_Volume = _StartVolume + (_TargetVolume - _StartVolume) * ((_FadeTimer.ElapsedMilliseconds / 1000f) / _FadeTime);
else
bool finished;
_Volume = _Fading.GetValue(out finished);
if (finished)
{
_Volume = _TargetVolume;
_FadeTimer.Stop();
_Fading = false;
if (_CloseStreamAfterFade)
_Terminated = true;
if (_PauseStreamAfterFade)
Paused = true;
if (_StopStreamAfterFade)
Stop();
switch (_AfterFadeAction)
{
case EStreamAction.Close:
_Terminated = true;
break;
case EStreamAction.Stop:
Stop();
break;
case EStreamAction.Pause:
Paused = true;
break;
}
_Fading = null;
}
}
}
+1 -1
View File
@@ -246,7 +246,7 @@ namespace Vocaluxe.Lib.Sound
if (!_Initialized)
return 0;
return _Buffer[player].NumHalfTones;
return CBuffer.NumHalfTones;
}
public float[] ToneWeigth(int player)
+83
View File
@@ -0,0 +1,83 @@
using System.Diagnostics;
namespace Vocaluxe.Lib.Sound
{
class CPt1
{
private float _CurrentTime;
private float _OldTime;
private readonly Stopwatch _Timer;
private readonly float _K;
private readonly float _T;
public float Time
{
get
{
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
return _CurrentTime + dt;
}
set
{
if (value < 0f)
return;
_CurrentTime = value;
_OldTime = value;
_Timer.Reset();
_Timer.Start();
}
}
public CPt1(float currentTime, float k, float t)
{
_CurrentTime = currentTime;
_OldTime = currentTime;
_Timer = new Stopwatch();
_K = k;
_T = t;
}
public float Update(float newTime)
{
_Timer.Stop();
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
float ts = 0f;
if (dt > 0)
ts = 1 / (_T / dt + 1);
_CurrentTime = ts * (_K * newTime - _OldTime) + _OldTime;
_OldTime = _CurrentTime;
_Timer.Restart();
return _CurrentTime;
}
public void Pause()
{
_Timer.Stop();
}
public void Resume()
{
_Timer.Start();
}
}
}
+81
View File
@@ -0,0 +1,81 @@
using System;
using System.Diagnostics;
namespace Vocaluxe.Lib.Sound
{
class CSyncTimer
{
private readonly CPt1 _ExternTime;
private readonly Stopwatch _Timer;
private float _SetValue;
public float Time
{
get
{
double nanosecPerTick = (1000.0 * 1000.0 * 1000.0) / Stopwatch.Frequency;
long ticks = _Timer.ElapsedTicks;
float dt = _Timer.ElapsedMilliseconds / 1000f;
if (Stopwatch.IsHighResolution && ticks != 0)
dt = (float)(ticks * nanosecPerTick / 1000000000.0);
return _SetValue + dt;
}
set
{
_ExternTime.Time = value;
_SetValue = value;
_Timer.Reset();
_Timer.Start();
}
}
public CSyncTimer(float currentTime, float k, float t)
{
_ExternTime = new CPt1(currentTime, k, t);
_Timer = new Stopwatch();
_SetValue = currentTime;
}
public float Update(float newTime)
{
float et = _ExternTime.Update(newTime);
float dt = Time;
float diff = et - dt;
if (Math.Abs(diff) > 0.05f)
{
_Timer.Reset();
_Timer.Start();
_SetValue = dt + diff;
dt = _SetValue;
//Console.WriteLine("DRIFTED!!! " + diff.ToString());
}
else
{
if (diff > 0.01f)
_SetValue += 0.000025f;
if (diff < -0.01f)
_SetValue -= 0.000025f;
}
//Console.WriteLine(diff.ToString());
return dt;
}
public void Pause()
{
_ExternTime.Pause();
_Timer.Stop();
}
public void Resume()
{
_ExternTime.Resume();
_Timer.Start();
}
}
}
+8
View File
@@ -17,6 +17,14 @@
namespace Vocaluxe.Lib.Sound
{
public enum EStreamAction
{
Nothing,
Pause,
Stop,
Close
}
struct SAudioStreams
{
public int Handle;
+73 -373
View File
@@ -18,432 +18,132 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Vocaluxe.Base;
using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Video.Acinerella
{
class CDecoder
{
private IntPtr _Instance = IntPtr.Zero; // acinerella instance
private IntPtr _Videodecoder = IntPtr.Zero; // acinerella video decoder instance
private readonly Stopwatch _LoopTimer = new Stopwatch();
private readonly Thread _Thread;
private readonly Object _MutexFramebuffer = new Object();
private readonly CFramebuffer _Framebuffer;
private readonly Object _MutexSyncSignals = new Object();
private bool _FileOpened;
private float _FrameDuration; // frame time in s
private float _LastDecodedTime; // time of last decoded frame
private float _LastShownTime; // time if the last shown frame in s
private float _Time;
private float _Gap;
private float _Start;
private bool _Loop;
private float _SetTime;
private float _SetGap;
private float _SetStart;
private bool _SetSkip;
private bool _Terminated;
private bool _FrameAvailable;
private bool _NoMoreFrames;
private readonly AutoResetEvent _EvWakeUp = new AutoResetEvent(false);
private bool _IsSleeping;
private int _WaitCount;
private float _SkipTime; // = Start + VideoGap
private string _FileName; // current video file name
private int _Width;
private int _Height;
private bool _Paused;
private float _LoopTime;
private CDecoderThread _Thread;
public float Length { get; private set; }
public bool Finished { get; private set; }
public CDecoder()
{
_Thread = new Thread(_Execute);
_Framebuffer = new CFramebuffer(10);
Length = 0;
Finished = true;
}
public float Length { get; private set; }
public bool Loop
{
get { return _Thread.Loop; }
set
{
{
_Thread.Loop = value;
if (value)
{
_LoopTime = _Thread.RequestTime;
_LoopTimer.Restart();
}
}
}
}
public bool Paused
{
set
{
lock (_MutexSyncSignals)
if (_Paused == value)
return;
_Paused = value;
if (_Paused)
{
_Paused = value;
if (_Paused)
_LoopTimer.Stop();
else
_LoopTimer.Start();
_LoopTimer.Stop();
_Thread.Pause();
}
else
{
_LoopTimer.Start();
_Thread.Resume();
}
}
}
public bool Loop { private get; set; }
public bool Finished { get; private set; }
public bool Open(string fileName)
{
if (_FileOpened)
if (_Thread != null)
return false;
if (!File.Exists(fileName))
return false;
_FileName = fileName;
//Do this here as one may want to get the length afterwards!
if (!_DoOpen())
return false;
_FileOpened = true;
_Thread.Priority = ThreadPriority.Normal;
_Thread.Name = Path.GetFileName(fileName);
_Thread.Start();
return true;
_Thread = new CDecoderThread();
if (_Thread.LoadFile(fileName))
{
Length = _Thread.Length;
Finished = false;
return _Thread.Start();
}
_Thread = null;
return false;
}
public void Close()
{
_Terminated = true;
if (_Thread != null)
_Thread.Stop();
Length = 0;
Finished = true;
}
public bool GetFrame(ref CTexture frame, float time, out float videoTime)
{
if (Finished)
{
videoTime = Length - _Gap;
return false;
}
if (Loop)
{
lock (_MutexSyncSignals)
time = _LoopTime + _LoopTimer.ElapsedMilliseconds / 1000f;
if (time >= Length)
{
_SetTime += _LoopTimer.ElapsedMilliseconds / 1000f;
do
{
time -= Length;
} while (time >= Length);
_LoopTime = time;
_LoopTimer.Restart();
}
}
else if (Math.Abs(_SetTime - time) >= 1f / 1000f) //Check 1 ms difference
{
lock (_MutexSyncSignals)
{
_SetTime = time;
}
}
else if (Math.Abs(_LastShownTime - time) < 1f / 1000 && frame != null) //Check 1 ms difference
{
videoTime = _LastShownTime;
return true;
}
_UploadNewFrame(ref frame);
videoTime = _LastShownTime;
else
time += _Gap;
_Thread.SyncTime(time);
bool finished;
_Thread.GetFrame(ref frame, ref time, out finished);
videoTime = time - _Gap;
if (finished) //Only set, not reset
Finished = true;
return frame != null;
}
public bool Skip(float start, float gap)
{
lock (_MutexSyncSignals)
{
_SetStart = start;
_SetGap = gap;
_SetSkip = true;
_NoMoreFrames = false;
Finished = false;
}
Finished = false;
_Gap = gap;
_Thread.Skip(start + gap);
if (Loop)
Loop = true; //Reset loop (timer)
return true;
}
#region Threading
private void _Skip()
{
_SkipTime = _Start + _Gap;
if (_SkipTime < 0)
_SkipTime = 0;
try
{
CAcinerella.AcSeek(_Videodecoder, -1, (Int64)(_SkipTime * 1000f));
}
catch (Exception e)
{
CLog.LogError("Error seeking video file \"" + _FileName + "\": " + e.Message);
}
_LastDecodedTime = _SkipTime;
lock (_MutexFramebuffer)
{
_Framebuffer.Clear();
}
_FrameAvailable = false;
}
private void _Execute()
{
while (!_Terminated)
{
bool skip;
lock (_MutexSyncSignals)
{
_Time = _SetTime;
skip = _SetSkip;
_SetSkip = false;
_Gap = _SetGap;
_Start = _SetStart;
_Loop = Loop;
}
if (skip)
_Skip();
if (!_FrameAvailable)
_Decode();
if (_FrameAvailable)
{
if (!_Framebuffer.IsFull())
{
_Copy();
_WaitCount = 0;
Thread.Sleep(1);
}
else if (_WaitCount > 3)
{
_IsSleeping = true;
_EvWakeUp.WaitOne();
}
else
{
Thread.Sleep((int)((_Framebuffer.Size - 2) * _FrameDuration * 1000));
_WaitCount++;
}
}
}
_Free();
}
private bool _DoOpen()
{
bool ok;
try
{
_Instance = CAcinerella.AcInit();
CAcinerella.AcOpen2(_Instance, _FileName);
var instance = (SACInstance)Marshal.PtrToStructure(_Instance, typeof(SACInstance));
Length = instance.Info.Duration / 1000f;
ok = instance.Opened;
}
catch (Exception)
{
ok = false;
}
if (!ok)
{
CLog.LogError("Error opening video file: " + _FileName);
return false;
}
int videoStreamIndex;
SACDecoder videodecoder;
try
{
_Videodecoder = CAcinerella.AcCreateVideoDecoder(_Instance);
videodecoder = (SACDecoder)Marshal.PtrToStructure(_Videodecoder, typeof(SACDecoder));
videoStreamIndex = videodecoder.StreamIndex;
}
catch (Exception)
{
CLog.LogError("Error opening video file (can't find decoder): " + _FileName);
_Free();
return false;
}
if (videoStreamIndex < 0)
{
_Free();
return false;
}
_Width = videodecoder.StreamInfo.VideoInfo.FrameWidth;
_Height = videodecoder.StreamInfo.VideoInfo.FrameHeight;
if (videodecoder.StreamInfo.VideoInfo.FramesPerSecond > 0)
_FrameDuration = 1f / (float)videodecoder.StreamInfo.VideoInfo.FramesPerSecond;
_LastDecodedTime = 0f;
_SetTime = 0f;
_Framebuffer.Init(_Width * _Height * 4);
_FrameAvailable = false;
return true;
}
private void _Decode()
{
const int minFrameDropCount = 4;
if (_Paused || _NoMoreFrames)
return;
float videoTime = _Time + _Gap;
float timeDifference = videoTime - _LastDecodedTime;
bool dropFrame = timeDifference >= (minFrameDropCount - 1) * _FrameDuration;
if (_Terminated)
return;
bool frameFinished = false;
if (dropFrame)
{
try
{
if (videoTime >= Length)
{
if (_Loop)
{
lock (_MutexSyncSignals)
{
_Start = 0;
_Gap = 0f;
_SetTime = 0;
}
_Skip();
}
else
{
_NoMoreFrames = true;
return;
}
}
else
{
var frameDropCount = (int)(timeDifference / _FrameDuration);
frameFinished = CAcinerella.AcSkipFrames(_Instance, _Videodecoder, frameDropCount);
}
}
catch (Exception)
{
CLog.LogError("Error AcSkipFrame " + _FileName);
}
}
if (!frameFinished)
{
try
{
frameFinished = CAcinerella.AcGetFrame(_Instance, _Videodecoder);
}
catch (Exception)
{
CLog.LogError("Error AcGetFrame " + _FileName);
}
}
if (frameFinished)
_FrameAvailable = true;
else
{
if (_Loop)
{
lock (_MutexSyncSignals)
{
_Start = 0f;
_Gap = 0f;
_SetTime = 0f;
}
_Skip();
}
else
_NoMoreFrames = true;
}
}
private void _Copy()
{
var videodecoder = (SACDecoder)Marshal.PtrToStructure(_Videodecoder, typeof(SACDecoder));
if (videodecoder.Buffer == IntPtr.Zero)
return;
_LastDecodedTime = (float)videodecoder.Timecode;
_Framebuffer.Put(videodecoder.Buffer, _LastDecodedTime);
_FrameAvailable = false;
}
private void _UploadNewFrame(ref CTexture frame)
{
lock (_MutexFramebuffer)
{
CFrame curFrame = _FindFrame();
if (curFrame != null)
{
CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, curFrame.Data);
lock (_MutexSyncSignals)
{
_LastShownTime = curFrame.Time;
}
}
else
{
if (_NoMoreFrames && _Framebuffer.IsEmpty())
Finished = true;
}
}
if (!Finished && _IsSleeping)
{
_IsSleeping = false;
_EvWakeUp.Set();
}
}
private CFrame _FindFrame()
{
CFrame result = null;
float now = _SetTime + _Gap;
float maxEnd = now - _FrameDuration * 2; //Get only frames younger than 2
CFrame frame;
bool paused = _Paused;
while ((frame = _Framebuffer.Get()) != null)
{
float frameEnd = frame.Time + _FrameDuration;
//Don't show frames that are shown during or after now
if (frameEnd >= now)
break; //All following frames are after that one
if (paused) // Don't modify anything
break;
_Framebuffer.SetRead();
//Get the last(newest) possible frame and skip the rest to force in-order showing
if (frameEnd <= maxEnd)
continue;
maxEnd = frameEnd;
result = frame;
}
return result;
}
private void _Free()
{
if (_Videodecoder != IntPtr.Zero)
CAcinerella.AcFreeDecoder(_Videodecoder);
if (_Instance != IntPtr.Zero)
{
CAcinerella.AcClose(_Instance);
CAcinerella.AcFree(_Instance);
}
}
#endregion Threading
}
}
@@ -0,0 +1,439 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using Vocaluxe.Base;
using VocaluxeLib.Draw;
namespace Vocaluxe.Lib.Video.Acinerella
{
//This class describes a thread decoding a video
//All public methods are meant to be called from "reader" thread only
//Most others are to be called by this thread (_Thread instance) only!
class CDecoderThread
{
private const float _LoopedRequestTime = -0.001f; //Magic const to detect if decoder looped automaticly
private Thread _Thread;
private readonly Object _BufferMutex = new Object();
private IntPtr _Instance = IntPtr.Zero; // acinerella instance
private IntPtr _Videodecoder = IntPtr.Zero; // acinerella video decoder instance
private readonly CFramebuffer _Framebuffer;
private float _LastDecodedTime; // time of last decoded frame
private float _LastShownTime = -1f; // time if the last shown frame in s IMPORTANT: Write only in context of reader
// time of last requested frame aka current should-be position (_LastDecodedTime should be >=_RequestTime)
//HAS to be < Length
public float RequestTime { get; private set; }
private bool _Paused;
private String _FileName;
private float _FrameDuration; // frame time in s
private int _Width;
private int _Height;
private bool _RequestSkip;
private bool _Terminated;
private bool _FrameAvailable;
private bool _NoMoreFrames;
private readonly AutoResetEvent _EvWakeUp = new AutoResetEvent(false);
private readonly AutoResetEvent _EvNoMoreFrames = new AutoResetEvent(false);
private bool _IsSleeping;
private int _WaitCount;
public float Length { get; private set; }
public bool Loop { get; set; }
public CDecoderThread()
{
_Framebuffer = new CFramebuffer(10);
_FrameDuration = 0.02f; // Set a reasonable standard till correct value is set
}
//Open the file and get the length.
public bool LoadFile(String fileName)
{
_FileName = fileName;
try
{
_Instance = CAcinerella.AcInit();
CAcinerella.AcOpen2(_Instance, fileName);
var instance = (SACInstance)Marshal.PtrToStructure(_Instance, typeof(SACInstance));
Length = instance.Info.Duration / 1000f;
bool ok = instance.Opened && Length > 0.001f;
if (ok)
return true;
_Free();
}
catch (Exception) {}
CLog.LogError("Error opening video file: " + _FileName);
_Instance = IntPtr.Zero;
return false;
}
public bool Start()
{
if (_Instance == IntPtr.Zero)
{
CLog.LogError("Tried to start a video file that is not open: " + _FileName);
return false;
}
if (_Thread != null)
{
CLog.LogError("Tried to start a video file that is already started: " + _FileName);
return false;
}
RequestTime = 0f;
_Thread = new Thread(_Execute) {Priority = ThreadPriority.Normal, Name = Path.GetFileName(_FileName)};
_Thread.Start();
return true;
}
public void Stop()
{
_Terminated = true;
_EvWakeUp.Set();
_EvNoMoreFrames.Set();
}
public void Pause()
{
if (_Paused)
return;
_Paused = true;
}
public void Resume()
{
if (!_Paused)
return;
_Paused = false;
}
//Sets the position to the given time discarding all decoded frames
public void Skip(float time)
{
//Problem: This is not threadsave
//Scenario: Clear buffer from main thread, decoder is in _Decode or _Copy
//Result: Cleared buffer contains 1 old item. This is a problem when skipping back: E.g. Loop:
//Old item has time=Length->Will not get removed
//Workaround: Check in _FindFrame to remove first old item
//Fix: Use mutex (TODO: Check overhead)
lock (_BufferMutex) //Cover clear, RequestTime=, _RequestSkip=
{
_Framebuffer.Clear();
RequestTime = time;
_LastShownTime = time - _FrameDuration; //Set this to time to detect overflow of time in FindFrame but subtract FrameDuration so GetFrame will get the first frame
_RequestSkip = true;
}
_EvNoMoreFrames.Set();
}
private CFramebuffer.CFrame _FindFrame(float now)
{
CFramebuffer.CFrame result = null;
CFramebuffer.CFrame frame;
_Framebuffer.ResetStack();
while ((frame = _Framebuffer.Pop()) != null)
{
//float frameEnd = frame.Time + _FrameDuration;
float frameTime = frame.Time;
if (frameTime > now)
{
//2 Cases: all following frames are after this one, or we have a loop and 'now' wrapped over
//First case is if we have no loop or we did not wrap or frame is before last one (last is the case if frame is already one of the new iterations, e.g. Last=19 now=1 frame=2)
if (!Loop || _LastShownTime <= now || frameTime < _LastShownTime)
break; //Following frames (incl this one) are after now, so do not consider any of them
}
// ReSharper disable CompareOfFloatsByEqualityOperator
else if (Loop && RequestTime == _LoopedRequestTime)
// ReSharper restore CompareOfFloatsByEqualityOperator
{
//Frame time might have wrapped but now did not
if (frameTime < _LastShownTime && _LastShownTime <= now)
break; //Following frames (incl this one) are after now, so do not consider any of them
}
//Get the last(newest) possible frame and skip the rest
if (result != null)
{
//Frame is to old -> Discard
result.SetRead();
}
result = frame;
if (_Paused)
break; //Just get 1 frame if paused otherwise a paused movie could move a bit
}
return result;
}
/// <summary>
/// Gets a frame
/// </summary>
/// <param name="frame">Referenz to texture where frame should be put in (can be null, then texture is created)</param>
/// <param name="time">Maximum start time for frame</param>
/// <param name="finished">Set to whether there are no more frames (stream finished, no loop, future calls will always return false)</param>
/// <returns>True if a new frame was gotten</returns>
public bool GetFrame(ref CTexture frame, ref float time, out bool finished)
{
bool result;
if (Math.Abs(_LastShownTime - time) < _FrameDuration && frame != null) //Check 1 frame difference
{
time = _LastShownTime;
result = false;
}
else
{
CFramebuffer.CFrame curFrame = _FindFrame(time);
if (curFrame != null)
{
CDraw.UpdateOrAddTexture(ref frame, _Width, _Height, curFrame.Data);
if (!_Paused)
curFrame.SetRead();
time = curFrame.Time;
_LastShownTime = time;
result = frame != null;
}
else
result = false;
if (_IsSleeping)
{
_IsSleeping = false;
_EvWakeUp.Set();
}
}
finished = _NoMoreFrames && _Framebuffer.IsEmpty();
return result;
}
//Time should be < Length
public void SyncTime(float time)
{
if (_Thread == null)
return; //Not initialized
if (RequestTime - time >= _FrameDuration)
{
//Jump back more than 1 frame. To guarantee the order in the buffer use Skip() which clears the buffer
Skip(time);
}
else if (time - RequestTime >= _FrameDuration)
{
//we were more than 1 frame to slow -> Jump forward (This is save, as the decoder will skip frames if necessary)
// ReSharper disable CompareOfFloatsByEqualityOperator
if (Loop && RequestTime == _LoopedRequestTime)
// ReSharper restore CompareOfFloatsByEqualityOperator
{
//In a loop our decoder may have reset RequestTime to 0 but we want a frame from the end of the video
//Skipping forward is fatal as it resets the decoder to decode already decoded frames causing lags
//So first check if we have a valid frame in our buffer
_Framebuffer.ResetStack();
CFramebuffer.CFrame frame;
while ((frame = _Framebuffer.Pop()) != null)
{
if (frame.Time + _FrameDuration >= time)
return;
}
//If we don't the Length might be inaccurate (e.g. last frame ends at 19.98 but Length=20)
if (time >= Length - 2 * _FrameDuration)
return;
}
RequestTime = time;
}
}
private bool _OpenVideoStream()
{
int videoStreamIndex;
SACDecoder decoder;
try
{
_Videodecoder = CAcinerella.AcCreateVideoDecoder(_Instance);
decoder = (SACDecoder)Marshal.PtrToStructure(_Videodecoder, typeof(SACDecoder));
videoStreamIndex = decoder.StreamIndex;
}
catch (Exception)
{
CLog.LogError("Error opening video file (can't find decoder): " + _FileName);
return false;
}
if (videoStreamIndex < 0)
return false;
_Width = decoder.StreamInfo.VideoInfo.FrameWidth;
_Height = decoder.StreamInfo.VideoInfo.FrameHeight;
if (decoder.StreamInfo.VideoInfo.FramesPerSecond > 0)
_FrameDuration = 1f / (float)decoder.StreamInfo.VideoInfo.FramesPerSecond;
_Framebuffer.Init(_Width * _Height * 4);
_FrameAvailable = false;
return true;
}
//Just call this if thread is not alive
private void _Free()
{
if (_Videodecoder != IntPtr.Zero)
CAcinerella.AcFreeDecoder(_Videodecoder);
if (_Instance != IntPtr.Zero)
{
CAcinerella.AcClose(_Instance);
CAcinerella.AcFree(_Instance);
}
}
// Skip to a given time (in s)
private void _Skip()
{
float skipTime = RequestTime; //Copy to variable to have consistent checks
if (skipTime < 0 || skipTime >= Length)
skipTime = 0;
try
{
CAcinerella.AcSeek(_Videodecoder, -1, (Int64)(skipTime * 1000f));
}
catch (Exception e)
{
CLog.LogError("Error seeking video file \"" + _FileName + "\": " + e.Message);
}
_LastDecodedTime = skipTime;
_FrameAvailable = false;
}
private void _Decode()
{
const int minFrameDropCount = 4;
if (_NoMoreFrames)
return;
float videoTime = RequestTime;
float timeDifference = videoTime - _LastDecodedTime;
bool dropFrame = timeDifference >= (minFrameDropCount - 1) * _FrameDuration;
bool hasFrameDecoded = false;
if (dropFrame)
{
try
{
var frameDropCount = (int)Math.Ceiling(timeDifference / _FrameDuration);
// Add 1 dropped frame per 16 frames (Power of 2 -> Div is fast) as skipping takes time too and we don't want to skip again
frameDropCount += frameDropCount / 16;
hasFrameDecoded = CAcinerella.AcSkipFrames(_Instance, _Videodecoder, frameDropCount);
}
catch (Exception)
{
CLog.LogError("Error AcSkipFrame " + _FileName);
}
}
if (!hasFrameDecoded)
{
try
{
hasFrameDecoded = CAcinerella.AcGetFrame(_Instance, _Videodecoder);
}
catch (Exception)
{
CLog.LogError("Error AcGetFrame " + _FileName);
}
}
if (hasFrameDecoded)
_FrameAvailable = true;
else
{
if (Loop)
{
RequestTime = _LoopedRequestTime;
_Skip();
}
else
_NoMoreFrames = true;
}
}
//Copies a frame to the buffer but does not set it as 'written'
//Returns true if frame data is now in buffer
private bool _CopyDecodedFrameToBuffer()
{
bool result;
var decoder = (SACDecoder)Marshal.PtrToStructure(_Videodecoder, typeof(SACDecoder));
if (decoder.Buffer != IntPtr.Zero)
{
_LastDecodedTime = (float)decoder.Timecode;
result = _Framebuffer.Put(decoder.Buffer, _LastDecodedTime);
}
else
result = false;
_FrameAvailable = false;
return result;
}
private void _Execute()
{
if (!_OpenVideoStream())
{
_Free();
Stop();
}
while (!_Terminated)
{
if (_NoMoreFrames)
_EvNoMoreFrames.WaitOne();
if (_RequestSkip)
{
_RequestSkip = false;
_NoMoreFrames = false;
_Skip();
}
if (!_FrameAvailable)
_Decode();
//Bail out if we want to skip
if (!_RequestSkip && _FrameAvailable)
{
if (!_Framebuffer.IsFull())
{
if (_CopyDecodedFrameToBuffer())
{
//Do not write to buffer if we want to skip. So check and write have to be done atomicly
lock (_BufferMutex)
{
if (_RequestSkip)
continue; //Frame is invalid if we want to skip
_Framebuffer.SetWritten();
}
}
_WaitCount = 0;
Thread.Sleep(5); //Sleep for a bit to give other threads an opportunity to run
}
else if (_WaitCount > 3)
{
_IsSleeping = true;
_EvWakeUp.WaitOne();
}
else
{
Thread.Sleep((int)(_Framebuffer.Size * _FrameDuration * 1000 / 2));
_WaitCount++;
}
}
}
_Free();
}
}
}
+55 -24
View File
@@ -20,24 +20,35 @@ using System.Runtime.InteropServices;
namespace Vocaluxe.Lib.Video.Acinerella
{
class CFrame
{
public readonly byte[] Data;
public float Time = -1;
public CFrame(int dataSize)
{
Data = new byte[dataSize];
}
}
class CFramebuffer
{
public class CFrame
{
private readonly CFramebuffer _Parent;
private readonly int _Index;
public readonly byte[] Data;
public float Time = -1;
public CFrame(CFramebuffer parent, int index, int dataSize)
{
_Parent = parent;
_Index = index;
Data = new byte[dataSize];
}
//Only call from reader thread
public void SetRead()
{
_Parent._SetRead(_Index);
}
}
private readonly CFrame[] _Frames;
private readonly int _Size;
private int _DataSize;
private int _Last;
private int _First;
private int _Next;
private bool _Initialized;
public int Size
@@ -45,21 +56,24 @@ namespace Vocaluxe.Lib.Video.Acinerella
get { return _Size; }
}
// Constructs a framebuffer with max. size frames
public CFramebuffer(int size)
{
_Size = size;
_Frames = new CFrame[size];
}
// Initializes the framebuffer with the size of each frame
// MUST be called before all others
public void Init(int dataSize)
{
_DataSize = dataSize;
for (int i = 0; i < _Size; i++)
_Frames[i] = new CFrame(dataSize);
_Frames[i] = new CFrame(this, i, dataSize);
_Initialized = true;
}
private int _Next(int current)
private int _GetNextIndex(int current)
{
current++;
return (current < _Size) ? current : 0;
@@ -67,7 +81,7 @@ namespace Vocaluxe.Lib.Video.Acinerella
public bool IsFull()
{
return _Next(_Last) == _First;
return _GetNextIndex(_Last) == _First;
}
public bool IsEmpty()
@@ -75,6 +89,7 @@ namespace Vocaluxe.Lib.Video.Acinerella
return _First == _Last;
}
//Only call from writer thread
public bool Put(IntPtr data, float time)
{
if (!_Initialized || IsFull())
@@ -82,27 +97,43 @@ namespace Vocaluxe.Lib.Video.Acinerella
CFrame frame = _Frames[_Last];
Marshal.Copy(data, frame.Data, 0, _DataSize);
frame.Time = time;
_Last = _Next(_Last);
return true;
}
public CFrame Get()
//Only call from writer thread after succesfull put
public void SetWritten()
{
return IsEmpty() ? null : _Frames[_First];
_Last = _GetNextIndex(_Last);
}
public bool SetRead()
//Only call from reader thread
public void ResetStack()
{
if (IsEmpty())
return false;
_First = _Next(_First);
return true;
_Next = _First;
}
//Pops the next frame if available
//You have to call ResetNext before the first call to this function and call the CFrame.SetRead to free the buffers
//Only call from reader thread
public CFrame Pop()
{
if (_Next == _Last)
return null;
CFrame res = _Frames[_Next];
_Next = _GetNextIndex(_Next);
return res;
}
private void _SetRead(int index)
{
if ((_First <= index && (index < _Next || _Next < _First)) || (_Next < _First && index < _Next))
_First = _GetNextIndex(index);
}
//Only call from reader thread
public void Clear()
{
_First = 0;
_Last = 0;
_Next = _First = _Last;
}
}
}
+2
View File
@@ -259,6 +259,7 @@ namespace Vocaluxe
Environment.Exit(Environment.ExitCode);
}
#if !DEBUG
[HandleProcessCorruptedStateExceptions]
private static void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
@@ -273,6 +274,7 @@ namespace Vocaluxe
CLog.LogError("Unhandled exception: " + e.Message + stackTrace);
_CloseProgram();
}
#endif
private static Assembly _AssemblyResolver(Object sender, ResolveEventArgs args)
{
+2 -2
View File
@@ -49,5 +49,5 @@ using System.Runtime.InteropServices;
// Revision
//
[assembly: AssemblyVersion("0.3.0.82")]
[assembly: AssemblyFileVersion("0.3.0.82")]
[assembly: AssemblyVersion("0.3.0.83")]
[assembly: AssemblyFileVersion("0.3.0.83")]
-6
View File
@@ -15,7 +15,6 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using ServerLib;
using Vocaluxe.Base;
using Vocaluxe.Base.Server;
using VocaluxeLib;
@@ -56,11 +55,6 @@ namespace Vocaluxe.Screens
_ThemeTexts = new string[] {_TextServerAddress, _TextServerNotRunning};
}
public override void LoadTheme(string xmlPath)
{
base.LoadTheme(xmlPath);
}
public override void OnShow()
{
base.OnShow();
+17 -13
View File
@@ -183,24 +183,28 @@ namespace Vocaluxe.Screens
public override void LoadTheme(string xmlPath)
{
bool ressourceOK = true;
//Vocaluxe-Logo
CDataBase.GetCreditsRessource("Logo_voc.png", ref _TexLogo);
ressourceOK &= CDataBase.GetCreditsRessource("Logo_voc.png", ref _TexLogo);
//Little stars for logo
CDataBase.GetCreditsRessource("PerfectNoteStar.png", ref _TexPerfectNoteStar);
ressourceOK &= CDataBase.GetCreditsRessource("PerfectNoteStar.png", ref _TexPerfectNoteStar);
CDataBase.GetCreditsRessource("redDot.png", ref _TexRedDot);
CDataBase.GetCreditsRessource("blueDot.png", ref _TexBlueDot);
ressourceOK &= CDataBase.GetCreditsRessource("redDot.png", ref _TexRedDot);
ressourceOK &= CDataBase.GetCreditsRessource("blueDot.png", ref _TexBlueDot);
CDataBase.GetCreditsRessource("brunzel.png", ref _TexNameBrunzel);
CDataBase.GetCreditsRessource("Darkice.png", ref _TexNameDarkice);
CDataBase.GetCreditsRessource("flokuep.png", ref _TexNameFlokuep);
CDataBase.GetCreditsRessource("flamefire.png", ref _TexNameFlamefire);
CDataBase.GetCreditsRessource("bohning.png", ref _TexNameBohning);
CDataBase.GetCreditsRessource("mesand.png", ref _TexNameMesand);
CDataBase.GetCreditsRessource("babene03.png", ref _TexNameBabene03);
CDataBase.GetCreditsRessource("pantero.png", ref _TexNamePantero);
CDataBase.GetCreditsRessource("Pinky007.png", ref _TexNamePinky007);
ressourceOK &= CDataBase.GetCreditsRessource("brunzel.png", ref _TexNameBrunzel);
ressourceOK &= CDataBase.GetCreditsRessource("Darkice.png", ref _TexNameDarkice);
ressourceOK &= CDataBase.GetCreditsRessource("flokuep.png", ref _TexNameFlokuep);
ressourceOK &= CDataBase.GetCreditsRessource("flamefire.png", ref _TexNameFlamefire);
ressourceOK &= CDataBase.GetCreditsRessource("bohning.png", ref _TexNameBohning);
ressourceOK &= CDataBase.GetCreditsRessource("mesand.png", ref _TexNameMesand);
ressourceOK &= CDataBase.GetCreditsRessource("babene03.png", ref _TexNameBabene03);
ressourceOK &= CDataBase.GetCreditsRessource("pantero.png", ref _TexNamePantero);
ressourceOK &= CDataBase.GetCreditsRessource("Pinky007.png", ref _TexNamePinky007);
if (!ressourceOK)
CLog.LogError("Could not load all ressources!", true, true);
//Prepare Text
int lastY = 280;
+16 -29
View File
@@ -44,7 +44,7 @@ namespace Vocaluxe.Screens
private string[] _TextDate;
private string[] _ParticleEffectNew;
private List<SScores>[] _Scores;
private List<SDBScoreEntry>[] _Scores;
private List<int> _NewEntryIDs;
private int _Round;
private int _Pos;
@@ -169,7 +169,7 @@ namespace Vocaluxe.Screens
string name = _Scores[_Round][_Pos + p].Name;
name += " [" + CLanguage.Translate(Enum.GetName(typeof(EGameDifficulty), _Scores[_Round][_Pos + p].Difficulty)) + "]";
if (_IsDuet)
name += " (P" + (_Scores[_Round][_Pos + p].LineNr + 1) + ")";
name += " (P" + (_Scores[_Round][_Pos + p].VoiceNr + 1) + ")";
_Texts[_TextName[p]].Text = name;
_Texts[_TextScore[p]].Text = _Scores[_Round][_Pos + p].Score.ToString("00000");
@@ -194,10 +194,6 @@ namespace Vocaluxe.Screens
base.OnShow();
_Round = 0;
_Pos = 0;
CPoints points = CGame.GetPoints();
_Scores = new List<SScores>[points.NumRounds];
for (int i = 0; i < _Scores.Length; i++)
_Scores[i] = new List<SScores>();
_NewEntryIDs.Clear();
_AddScoresToDB();
_LoadScores();
@@ -231,15 +227,14 @@ namespace Vocaluxe.Screens
private void _LoadScores()
{
CPoints points = CGame.GetPoints();
if (points == null)
return;
_Pos = 0;
for (int round = 0; round < points.NumRounds; round++)
int rounds = CGame.NumRounds;
_Scores = new List<SDBScoreEntry>[rounds];
for (int round = 0; round < rounds; round++)
{
SPlayer player = points.GetPlayer(round, CGame.NumPlayer)[0];
CDataBase.LoadScore(out _Scores[round], player);
int songID = CGame.GetSong(round).ID;
EGameMode gameMode = CGame.GetGameMode(round);
_Scores[round] = CDataBase.LoadScore(songID, gameMode);
}
}
@@ -247,7 +242,7 @@ namespace Vocaluxe.Screens
{
_IsDuet = false;
CPoints points = CGame.GetPoints();
CSong song = CGame.GetSong(_Round + 1);
CSong song = CGame.GetSong(_Round);
if (song == null)
return;
@@ -255,7 +250,7 @@ namespace Vocaluxe.Screens
if (points.NumRounds > 1)
_Texts[_TextSongName].Text += " (" + (_Round + 1) + "/" + points.NumRounds + ")";
switch (CGame.GetGameMode(_Round + 1))
switch (CGame.GetGameMode(_Round))
{
case EGameMode.TR_GAMEMODE_NORMAL:
_Texts[_TextSongMode].Text = "TR_GAMEMODE_NORMAL";
@@ -284,28 +279,20 @@ namespace Vocaluxe.Screens
private void _ChangePos(int num)
{
if (num > 0)
{
if (_Pos + num + _NumEntrys < _Scores[_Round].Count)
_Pos += num;
}
if (num < 0)
if (_Scores[_Round].Count == 0)
_Pos = 0;
else
{
_Pos += num;
if (_Pos < 0)
_Pos = 0;
_Pos = _Pos.Clamp(0, _Scores[_Round].Count - 1);
}
}
private void _ChangeRound(int num)
{
CPoints points = CGame.GetPoints();
if (_Round + num < points.NumRounds && _Round + num > -1)
_Round += num;
else if (_Round + num >= points.NumRounds)
_Round = points.NumRounds - 1;
else if (_Round + num < 0)
_Round = 0;
_Round += num;
_Round = _Round.Clamp(0, points.NumRounds - 1);
_UpdateRound();
}
+12 -23
View File
@@ -15,7 +15,6 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using Vocaluxe.Base;
@@ -38,9 +37,8 @@ namespace Vocaluxe.Screens
private readonly string[] _IntroVideo = new string[] {"IntroIn", "IntroMid", "IntroOut"};
private Thread _SongLoaderThread;
private Stopwatch _Timer;
private bool _SkipIntro;
private int _CurrentIntroVideoNr;
private int _CurrentIntroVideo;
private bool _IntroOutPlayed;
private CVideoPlayer[] _Intros;
@@ -54,7 +52,6 @@ namespace Vocaluxe.Screens
_Intros = new CVideoPlayer[_IntroVideo.Length];
for (int i = 0; i < _Intros.Length; i++)
_Intros[i] = new CVideoPlayer();
_Timer = new Stopwatch();
}
public override bool HandleInput(SKeyEvent keyEvent)
@@ -109,7 +106,7 @@ namespace Vocaluxe.Screens
CLanguage.Translate("TR_SCREENLOAD_LOADED") + ")";
_SkipIntro = false;
_CurrentIntroVideoNr = -1;
_CurrentIntroVideo = -1;
_IntroOutPlayed = false;
if (CConfig.VideoBackgrounds == EOffOn.TR_CONFIG_ON)
@@ -135,7 +132,6 @@ namespace Vocaluxe.Screens
CLog.StartBenchmark(0, "Load Songs Full");
_SongLoaderThread.IsBackground = true;
_SongLoaderThread.Start();
_Timer.Start();
if (CConfig.BackgroundMusic == EOffOn.TR_CONFIG_ON &&
CConfig.BackgroundMusicSource == EBackgroundMusicSource.TR_CONFIG_NO_OWN_MUSIC && !_BGMusicStarted)
@@ -155,11 +151,6 @@ namespace Vocaluxe.Screens
{
_CheckStartIntroVideos();
if (CSettings.GameState == EGameState.EditTheme)
_Timer.Stop();
else
_Timer.Start();
bool next = CConfig.CoverLoading != ECoverLoading.TR_CONFIG_COVERLOADING_ATSTART || CSongs.CoverLoaded;
if ((_IntroOutPlayed || _SkipIntro) && next && CSettings.GameState != EGameState.EditTheme && CSongs.SongsLoaded)
@@ -191,8 +182,8 @@ namespace Vocaluxe.Screens
{
_DrawBG();
foreach (CVideoPlayer videoPlayer in _Intros)
videoPlayer.Draw();
if (_CurrentIntroVideo >= 0 && _CurrentIntroVideo < _Intros.Length)
_Intros[_CurrentIntroVideo].Draw();
_DrawFG();
return true;
@@ -201,8 +192,6 @@ namespace Vocaluxe.Screens
public override void OnClose()
{
base.OnClose();
_Timer.Stop();
_Timer.Reset();
foreach (CVideoPlayer videoPlayer in _Intros)
videoPlayer.Close();
@@ -228,24 +217,24 @@ namespace Vocaluxe.Screens
return;
}
if (_CurrentIntroVideoNr < 0)
if (_CurrentIntroVideo < 0)
{
_CurrentIntroVideoNr = 0;
_CurrentIntroVideo = 0;
_Intros[0].Start();
}
else if (_CurrentIntroVideoNr == 0 && _Intros[0].IsFinished && CConfig.CoverLoading == ECoverLoading.TR_CONFIG_COVERLOADING_ATSTART)
else if (_CurrentIntroVideo == 0 && _Intros[0].IsFinished && CConfig.CoverLoading == ECoverLoading.TR_CONFIG_COVERLOADING_ATSTART)
{
_CurrentIntroVideoNr = 1;
_CurrentIntroVideo = 1;
_Intros[1].Loop = true;
_Intros[1].Start();
}
else if ((_CurrentIntroVideoNr == 1 && CSongs.CoverLoaded) ||
(_CurrentIntroVideoNr == 0 && _Intros[0].IsFinished))
else if ((_CurrentIntroVideo == 1 && CSongs.CoverLoaded) ||
(_CurrentIntroVideo == 0 && _Intros[0].IsFinished))
{
_CurrentIntroVideoNr = 2;
_CurrentIntroVideo = 2;
_Intros[2].Start();
}
else if (_CurrentIntroVideoNr == 2 && _Intros[2].IsFinished)
else if (_CurrentIntroVideo == 2 && _Intros[2].IsFinished)
_IntroOutPlayed = true;
}
}
+5 -6
View File
@@ -241,7 +241,7 @@ namespace Vocaluxe.Screens
break;
case Keys.F10:
if (CGame.GetNumSongs() == 1 && CGame.GetSong(1).IsDuet)
if (CGame.GetNumSongs() == 1 && CGame.GetSong(0).IsDuet)
{
CSelectSlide selectSlideDuetPart = _SelectSlides[_SelectSlideDuetPlayer[_SelectingFastPlayerNr - 1]];
selectSlideDuetPart.Selection = (selectSlideDuetPart.Selection + 1) % 2;
@@ -599,7 +599,7 @@ namespace Vocaluxe.Screens
_CheckMics();
_CheckPlayers();
CSong firstSong = CGame.GetSong(1);
CSong firstSong = CGame.GetSong(0);
for (int i = 0; i < CSettings.MaxNumPlayer; i++)
{
@@ -627,12 +627,11 @@ namespace Vocaluxe.Screens
private void _StartSong()
{
for (int i = 0; i < CGame.NumPlayer; i++)
if (CGame.GetNumSongs() == 1 && CGame.GetSong(0).IsDuet)
{
if (CGame.GetNumSongs() == 1 && CGame.GetSong(1).IsDuet)
for (int i = 0; i < CGame.NumPlayer; i++)
CGame.Players[i].VoiceNr = _SelectSlides[_SelectSlideDuetPlayer[i]].Selection;
}
CGraphics.FadeTo(EScreens.ScreenSing);
}
@@ -658,7 +657,7 @@ namespace Vocaluxe.Screens
if (_Texts["TextPlayer" + i].Text == "")
_Texts["TextPlayer" + i].Text = CProfiles.GetPlayerName(-1, i);
_Equalizers["EqualizerPlayer" + i].Visible = true;
if (CGame.GetNumSongs() == 1 && CGame.GetSong(1).IsDuet)
if (CGame.GetNumSongs() == 1 && CGame.GetSong(0).IsDuet)
_SelectSlides["SelectSlideDuetPlayer" + i].Visible = true;
}
else
+22 -71
View File
@@ -17,7 +17,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Windows.Forms;
using Vocaluxe.Base;
using Vocaluxe.Lib.Sound;
@@ -26,21 +25,14 @@ using VocaluxeLib.Menu;
namespace Vocaluxe.Screens
{
struct SDelayTest
{
public Stopwatch Timer;
public float Delay;
}
class CScreenOptionsRecord : CMenu
{
// Version number for theme files. Increment it, if you've changed something on the theme files!
protected override int _ScreenVersion
{
get { return 3; }
get { return 4; }
}
private const float _MaxDelayTime = 1f;
private const string _SelectSlideRecordDevices = "SelectSlideRecordDevices";
private const string _SelectSlideRecordChannel1 = "SelectSlideRecordChannel1";
@@ -53,6 +45,9 @@ namespace Vocaluxe.Screens
private const string _ButtonExit = "ButtonExit";
private const string _ButtonDelayTest = "ButtonDelayTest";
private const string _TextChannel1 = "TextChannel1";
private const string _TextChannel2 = "TextChannel2";
private const string _TextDelayChannel1 = "TextDelayChannel1";
private const string _TextDelayChannel2 = "TextDelayChannel2";
@@ -65,9 +60,7 @@ namespace Vocaluxe.Screens
private ReadOnlyCollection<CRecordDevice> _Devices;
private int _DeviceNr;
private SDelayTest[] _DelayTest;
private bool _DelayTestRunning;
private int _DelaySound;
private readonly CDelayTest _DelayTest = new CDelayTest(2);
public override void Init()
{
@@ -77,7 +70,7 @@ namespace Vocaluxe.Screens
values.AddRange(_StaticEnergyChannel);
_ThemeStatics = values.ToArray();
_ThemeTexts = new string[] {_TextWarning, _TextDelayChannel1, _TextDelayChannel2};
_ThemeTexts = new string[] {_TextWarning, _TextChannel1, _TextChannel2, _TextDelayChannel1, _TextDelayChannel2};
_ThemeButtons = new string[] {_ButtonExit, _ButtonDelayTest};
_ThemeSelectSlides = new string[] {_SelectSlideRecordDevices, _SelectSlideRecordChannel1, _SelectSlideRecordChannel2, _SelectSlideDelay};
_ThemeEqualizers = new string[] {_EqualizerChannel1, _EqualizerChannel2};
@@ -221,47 +214,13 @@ namespace Vocaluxe.Screens
for (int i = 0; i < CSettings.MaxNumPlayer; i++)
CSound.AnalyzeBuffer(i);
if (_DelayTest != null)
if (_DelayTest.Running)
{
for (int i = 0; i < _DelayTest.Length - 1; i++)
{
if (_DelayTestRunning && !_DelayTest[i].Timer.IsRunning)
{
if (CSound.GetPosition(_DelaySound) > 0f)
{
_DelayTest[i].Timer.Reset();
_DelayTest[i].Timer.Start();
}
}
if (_DelayTest[i].Timer.IsRunning)
{
int player = 0;
if (i == 0)
player = _SelectSlides[_SelectSlideRecordChannel1].Selection;
if (i == 1)
player = _SelectSlides[_SelectSlideRecordChannel2].Selection;
if (_DelayTest[i].Timer.ElapsedMilliseconds > _MaxDelayTime * 1000f || player == 0)
{
_DelayTest[i].Delay = 0f;
_DelayTest[i].Timer.Stop();
_DelayTestRunning = false;
}
else if (CSound.RecordGetMaxVolume(player - 1) > 0.1f &&
(CSound.RecordGetToneAbs(player - 1) == 9 || CSound.RecordGetToneAbs(player - 1) == 21 || CSound.RecordGetToneAbs(player - 1) == 33))
{
_DelayTest[i].Delay = _DelayTest[i].Timer.ElapsedMilliseconds;
_DelayTest[i].Timer.Stop();
_DelayTestRunning = false;
}
}
}
_Texts[_TextDelayChannel1].Text = _DelayTest[0].Delay.ToString("000") + " ms";
_Texts[_TextDelayChannel2].Text = _DelayTest[1].Delay.ToString("000") + " ms";
_DelayTest.Update();
_Texts[_TextDelayChannel1].Text = (_DelayTest.Delays[0] == 0) ? "???" : _DelayTest.Delays[0].ToString("000") + " ms";
_Texts[_TextDelayChannel2].Text = (_DelayTest.Delays[1] == 0) ? "???" : _DelayTest.Delays[1].ToString("000") + " ms";
}
if (_CheckMicConfig())
{
_ChannelEnergy[0] = 0f;
@@ -325,21 +284,9 @@ namespace Vocaluxe.Screens
_Statics[_StaticWarning].Visible = false;
_Texts[_TextWarning].Visible = false;
_DelayTest = null;
if (_Devices != null)
{
_DelayTest = new SDelayTest[2];
for (int i = 0; i < _DelayTest.Length - 1; i++)
{
_DelayTest[i].Timer = new Stopwatch();
_DelayTest[i].Delay = 0f;
}
}
_DelayTest.Reset();
_SelectSlides[_SelectSlideDelay].Selection = CConfig.MicDelay / 20;
_DelayTestRunning = false;
_DelaySound = -1;
}
public override void OnShowFinish()
@@ -391,7 +338,7 @@ namespace Vocaluxe.Screens
base.OnClose();
CSound.RecordStop();
_DelayTest = null;
_DelayTest.Reset();
CBackgroundMusic.Disabled = false;
}
@@ -444,6 +391,12 @@ namespace Vocaluxe.Screens
CSound.RecordStart();
}
private void _SetPlayerColors()
{
_Texts[_TextChannel1].Color = CTheme.GetPlayerColor(_SelectSlides[_SelectSlideRecordChannel1].Selection);
_Texts[_TextChannel2].Color = CTheme.GetPlayerColor(_SelectSlides[_SelectSlideRecordChannel2].Selection);
}
private void _SetMicConfig()
{
if (_DeviceNr < 0)
@@ -451,6 +404,7 @@ namespace Vocaluxe.Screens
CRecordDevice device = _Devices[_DeviceNr];
device.PlayerChannel1 = _SelectSlides[_SelectSlideRecordChannel1].Selection;
device.PlayerChannel2 = _SelectSlides[_SelectSlideRecordChannel2].Selection;
_SetPlayerColors();
}
private void _UpdateChannels()
@@ -459,6 +413,7 @@ namespace Vocaluxe.Screens
_SelectSlides[_SelectSlideRecordChannel2].Selection = _Devices[_DeviceNr].PlayerChannel2;
_SaveMicConfig();
_SetPlayerColors();
}
private bool _CheckMicConfig()
@@ -494,12 +449,8 @@ namespace Vocaluxe.Screens
private void _TestDelay()
{
_SaveMicConfig();
if (_DelayTest == null)
return;
_DelaySound = CSound.PlaySound(ESounds.T440);
_DelayTestRunning = true;
_DelayTest.Reset();
_DelayTest.Start(new int[] {_SelectSlides[_SelectSlideRecordChannel1].Selection - 1, _SelectSlides[_SelectSlideRecordChannel2].Selection - 1});
}
private void _GetFirstConfiguredRecordDevice(ref int device)
@@ -15,12 +15,10 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Windows.Forms;
using Vocaluxe.Base;
using VocaluxeLib;
using VocaluxeLib.Menu;
using VocaluxeLib.Draw;
namespace Vocaluxe.Screens
{
+18 -19
View File
@@ -124,7 +124,8 @@ namespace Vocaluxe.Screens
public override void OnShow()
{
base.OnShow();
_Round = CGame.NumRounds > 1 ? 0 : 1;
//-1 --> Show average
_Round = CGame.NumRounds > 1 ? -1 : 0;
_Points = CGame.GetPoints();
_SavePlayedSongs();
@@ -137,8 +138,8 @@ namespace Vocaluxe.Screens
public override bool UpdateGame()
{
var players = new SPlayer[CGame.NumPlayer];
if (_Round != 0)
players = _Points.GetPlayer(_Round - 1, CGame.NumPlayer);
if (_Round >= 0)
players = _Points.GetPlayer(_Round, CGame.NumPlayer);
else
{
for (int i = 0; i < CGame.NumRounds; i++)
@@ -186,8 +187,8 @@ namespace Vocaluxe.Screens
if (_SlideShowBGAvailable)
_SlideShowBG.Draw();
else
base._DrawBG();
base._DrawFG();
_DrawBG();
_DrawFG();
return true;
}
@@ -274,7 +275,7 @@ namespace Vocaluxe.Screens
{
CSong song = null;
var players = new SPlayer[CGame.NumPlayer];
if (_Round != 0)
if (_Round >= 0)
{
song = CGame.GetSong(_Round);
if (song == null)
@@ -282,8 +283,8 @@ namespace Vocaluxe.Screens
_Texts[_TextSong].Text = song.Artist + " - " + song.Title;
if (_Points.NumRounds > 1)
_Texts[_TextSong].Text += " (" + _Round + "/" + _Points.NumRounds + ")";
players = _Points.GetPlayer(_Round - 1, CGame.NumPlayer);
_Texts[_TextSong].Text += " (" + (_Round + 1) + "/" + _Points.NumRounds + ")";
players = _Points.GetPlayer(_Round, CGame.NumPlayer);
}
else
{
@@ -395,16 +396,14 @@ namespace Vocaluxe.Screens
private void _ChangeRound(int num)
{
if ((_Round + num) <= _Points.NumRounds && (_Round + num > 0))
{
_Round += num;
_UpdateRatings();
}
else if (num < 0 && _Round == 1 && CGame.NumRounds > 1)
{
_Round = 0;
_UpdateRatings();
}
if (_Points.NumRounds < 1)
return;
_Round += num;
_Round = _Round.Clamp(-1, _Points.NumRounds - 1);
if (_Round >= _Points.NumRounds)
_Round = _Points.NumRounds - 1;
_UpdateRatings();
}
private void _SavePlayedSongs()
@@ -429,7 +428,7 @@ namespace Vocaluxe.Screens
private bool _UpdateBackground()
{
string[] photos = CVocaluxeServer.getPhotosOfThisRound();
string[] photos = CVocaluxeServer.GetPhotosOfThisRound();
_SlideShowBG.RemoveSlideShowTextures();
foreach (string photo in photos)
_SlideShowBG.AddSlideShowTexture(photo);
+49 -29
View File
@@ -39,7 +39,7 @@ namespace Vocaluxe.SongQueue
class CSongQueue : ISongQueue
{
private List<SSongQueueEntry> _SongQueue;
private int _CurrentSong;
private int _CurrentRound;
private CPoints _Points;
#region Implementation
@@ -52,9 +52,7 @@ namespace Vocaluxe.SongQueue
public EGameMode GetCurrentGameMode()
{
if (_CurrentSong >= 0 && _CurrentSong < _SongQueue.Count)
return _SongQueue[_CurrentSong].GameMode;
return EGameMode.TR_GAMEMODE_NORMAL;
return GetGameMode(_CurrentRound);
}
public bool AddVisibleSong(int visibleIndex, EGameMode gameMode)
@@ -105,7 +103,7 @@ namespace Vocaluxe.SongQueue
public void Reset()
{
_CurrentSong = -1;
_CurrentRound = -1;
}
public void Start(SPlayer[] players)
@@ -113,39 +111,51 @@ namespace Vocaluxe.SongQueue
_Points = new CPoints(_SongQueue.Count, players);
}
public void NextRound(SPlayer[] players)
public void StartNextRound(SPlayer[] players)
{
if (_CurrentSong < _SongQueue.Count && _SongQueue.Count > 0)
if (IsFinished())
return;
if (_CurrentRound > -1)
{
if (_CurrentSong > -1)
{
_Points.SetPoints(
_CurrentSong,
_SongQueue[_CurrentSong].SongID,
players,
_SongQueue[_CurrentSong].GameMode == EGameMode.TR_GAMEMODE_MEDLEY,
_SongQueue[_CurrentSong].GameMode == EGameMode.TR_GAMEMODE_DUET,
_SongQueue[_CurrentSong].GameMode == EGameMode.TR_GAMEMODE_SHORTSONG);
}
_CurrentSong++;
_Points.SetPoints(
_CurrentRound,
_SongQueue[_CurrentRound].SongID,
players,
_SongQueue[_CurrentRound].GameMode);
}
_CurrentRound++;
}
public bool IsFinished()
{
return _CurrentSong == _SongQueue.Count || _SongQueue.Count == 0;
return _CurrentRound >= _SongQueue.Count || _SongQueue.Count == 0;
}
/// <summary>
/// Get current round nr (1 ~ n)
/// </summary>
/// <returns>current round nr (1 ~ n)</returns>
public int GetCurrentRoundNr()
{
return _CurrentSong + 1;
return _CurrentRound + 1;
}
/// <summary>
/// Returns current round
/// </summary>
/// <returns>Current round (0 based)</returns>
public int GetCurrentRound()
{
return _CurrentRound;
}
/// <summary>
/// Get current song
/// </summary>
/// <returns>Song of current round or null if there is none/game finished</returns>
public CSong GetSong()
{
if (_CurrentSong >= 0 && _CurrentSong < _SongQueue.Count)
return CGameModes.Get(_SongQueue[_CurrentSong].GameMode).GetSong(_SongQueue[_CurrentSong].SongID);
return null;
return GetSong(_CurrentRound);
}
public int GetNumSongs()
@@ -153,18 +163,28 @@ namespace Vocaluxe.SongQueue
return _SongQueue.Count;
}
public CSong GetSong(int num)
/// <summary>
/// Get song of specified round
/// </summary>
/// <param name="round">Round (0 based)</param>
/// <returns>Current song or null if out of bounds</returns>
public CSong GetSong(int round)
{
if (num - 1 < _SongQueue.Count && num > 0)
return CSongs.GetSong(_SongQueue[num - 1].SongID);
if (round < _SongQueue.Count && round >= 0)
return CSongs.GetSong(_SongQueue[round].SongID);
return null;
}
public EGameMode GetGameMode(int num)
/// <summary>
/// Get gameMode of specified round
/// </summary>
/// <param name="round">Round (0 based)</param>
/// <returns>Current song or null if out of bounds</returns>
public EGameMode GetGameMode(int round)
{
if (num - 1 < _SongQueue.Count && num > 0)
return _SongQueue[num - 1].GameMode;
if (round < _SongQueue.Count && round >= 0)
return _SongQueue[round].GameMode;
return EGameMode.TR_GAMEMODE_NORMAL;
}
+6 -6
View File
@@ -25,8 +25,6 @@ namespace Vocaluxe.SongQueue
{
void Init();
EGameMode GetCurrentGameMode();
bool AddVisibleSong(int visibleIndex, EGameMode gameMode);
bool AddSong(int absoluteIndex, EGameMode gameMode);
bool RemoveVisibleSong(int visibleIndex);
@@ -35,15 +33,17 @@ namespace Vocaluxe.SongQueue
void Reset();
void Start(SPlayer[] players);
void NextRound(SPlayer[] players);
void StartNextRound(SPlayer[] players);
bool IsFinished();
int GetCurrentRoundNr();
CPoints GetPoints();
int GetNumSongs();
int GetCurrentRoundNr();
CSong GetSong();
CSong GetSong(int num);
EGameMode GetGameMode(int num);
CSong GetSong(int round);
EGameMode GetCurrentGameMode();
EGameMode GetGameMode(int round);
}
}
+6 -1
View File
@@ -212,11 +212,14 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Base\CBackgroundMusic.cs" />
<Compile Include="Lib\Sound\CBuffer.cs" />
<Compile Include="Base\CConfig.cs" />
<Compile Include="Base\CCover.cs" />
<Compile Include="Base\CCursor.cs" />
<Compile Include="Base\CDataBase.cs" />
<Compile Include="Base\CDraw.cs" />
<Compile Include="Lib\Sound\CPt1.cs" />
<Compile Include="Lib\Sound\CSyncTimer.cs" />
<Compile Include="Base\Fonts\CFont.cs" />
<Compile Include="Base\CGame.cs" />
<Compile Include="Base\CController.cs" />
@@ -251,7 +254,9 @@
<Compile Include="Lib\Input\CControllerFramework.cs" />
<Compile Include="Lib\Sound\CGstreamerSharpAudio.cs" />
<Compile Include="Lib\Video\Acinerella\CDecoder.cs" />
<Compile Include="Lib\Video\Acinerella\CDecoderThread.cs" />
<Compile Include="Lib\Video\Acinerella\CFramebuffer.cs" />
<Compile Include="Lib\Sound\CDelayTest.cs" />
<Compile Include="Screens\CPopupScreenServerQR.cs" />
<Compile Include="Screens\CScreenOptionsVideoAdjustments.cs" />
<Compile Include="SongQueue\CSongQueue.cs" />
@@ -484,4 +489,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+2
View File
@@ -22,6 +22,7 @@
position: relative;
height: 100%;
width: 100%;
background-color: #000000;
background-color: rgba(0,0,0,0.7);
}
@@ -30,6 +31,7 @@
height: 100%;
top: 0;
margin: 0;
background: #000000;
background: rgba(0, 0, 0, 0.3);
display: none;
position: fixed;
+66
View File
@@ -0,0 +1,66 @@
#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.Diagnostics;
namespace VocaluxeLib
{
public class CFading
{
private readonly float _FromValue;
private readonly float _ToValue;
private readonly float _Duration; //in ms
private readonly Stopwatch _Timer = new Stopwatch();
/// <summary>
/// Starts a fading process adjusting between 2 values over a given amount of time
/// </summary>
/// <param name="fromValue">Start value</param>
/// <param name="toValue">Target value</param>
/// <param name="duration">Duration of the fading in seconds</param>
public CFading(float fromValue, float toValue, float duration)
{
if (duration < 0)
duration = 0;
_FromValue = fromValue;
_ToValue = toValue;
_Duration = duration * 1000f;
_Timer.Start();
}
/// <summary>
/// Gets the current value and sets finished
/// </summary>
/// <param name="finished">Set to whether fading has finished</param>
/// <returns>Current value (between from and to values)</returns>
public float GetValue(out bool finished)
{
float result;
if (_Timer.ElapsedMilliseconds < _Duration)
{
result = (_Timer.ElapsedMilliseconds / _Duration) * (_ToValue - _FromValue) + _FromValue;
finished = false;
}
else
{
result = _ToValue;
finished = true;
}
return result;
}
}
}
+9
View File
@@ -47,6 +47,15 @@ namespace VocaluxeLib
return (int)result;
}
public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
if (val.CompareTo(min) < 0)
return min;
if (val.CompareTo(max) > 0)
return max;
return val;
}
/// <summary>
/// Concat strings into one string with ", " as separator.
/// </summary>
+2
View File
@@ -355,6 +355,7 @@ namespace VocaluxeLib
[Flags]
public enum EUserRole
{
// ReSharper disable InconsistentNaming
TR_USERROLE_GUEST = 0,
TR_USERROLE_NORMAL = 1,
TR_USERROLE_ADMIN = 2,
@@ -362,5 +363,6 @@ namespace VocaluxeLib
TR_USERROLE_ADDSONGSUSER = 8,
TR_USERROLE_PLAYLISTEDITOR = 16,
TR_USERROLE_PROFILEEDITOR = 32
// ReSharper restore InconsistentNaming
}
}
+1 -2
View File
@@ -19,11 +19,10 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace VocaluxeLib
{
public static class Extensions
public static class CExtensions
{
/// <summary>
/// Resizes the given list to the given size. Removes elements or adds default values
+4 -10
View File
@@ -35,15 +35,13 @@ namespace VocaluxeLib.Game
_Rounds[round, player].Points = 0f;
_Rounds[round, player].PointsGoldenNotes = 0f;
_Rounds[round, player].PointsLineBonus = 0f;
_Rounds[round, player].Medley = false;
_Rounds[round, player].Duet = false;
_Rounds[round, player].ShortSong = false;
_Rounds[round, player].GameMode = EGameMode.TR_GAMEMODE_NORMAL;
_Rounds[round, player].SongFinished = false;
}
}
}
public void SetPoints(int round, int songID, SPlayer[] players, bool medley, bool duet, bool shortSong)
public void SetPoints(int round, int songID, SPlayer[] players, EGameMode gameMode)
{
long dateTicks = DateTime.Now.Ticks;
for (int player = 0; player < players.Length; player++)
@@ -53,9 +51,7 @@ namespace VocaluxeLib.Game
_Rounds[round, player].Points = players[player].Points;
_Rounds[round, player].PointsGoldenNotes = players[player].PointsGoldenNotes;
_Rounds[round, player].PointsLineBonus = players[player].PointsLineBonus;
_Rounds[round, player].Medley = medley;
_Rounds[round, player].Duet = duet;
_Rounds[round, player].ShortSong = shortSong;
_Rounds[round, player].GameMode = gameMode;
_Rounds[round, player].DateTicks = dateTicks;
_Rounds[round, player].SongFinished = players[player].SongFinished;
}
@@ -87,9 +83,7 @@ namespace VocaluxeLib.Game
players[p].PointsLineBonus = _Rounds[round, p].PointsLineBonus;
players[p].SongID = _Rounds[round, p].SongID;
players[p].VoiceNr = _Rounds[round, p].VoiceNr;
players[p].Medley = _Rounds[round, p].Medley;
players[p].Duet = _Rounds[round, p].Duet;
players[p].ShortSong = _Rounds[round, p].ShortSong;
players[p].GameMode = _Rounds[round, p].GameMode;
players[p].DateTicks = _Rounds[round, p].DateTicks;
players[p].SongFinished = _Rounds[round, p].SongFinished;
players[p].ProfileID = _Rounds[round, p].ProfileID;
+2
View File
@@ -155,6 +155,8 @@ namespace VocaluxeLib
public interface ILog
{
void LogError(string errorText);
void LogDebug(string text);
void LogSongInfo(string text);
}
public interface IFonts
+4 -5
View File
@@ -54,8 +54,8 @@ namespace VocaluxeLib.Menu
private bool _ThemeLoaded;
private int _SlideShowCurrent;
private Stopwatch _SlideShowTimer = new Stopwatch();
private List<CTexture> _SlideShowTextures = new List<CTexture>();
private readonly Stopwatch _SlideShowTimer = new Stopwatch();
private readonly List<CTexture> _SlideShowTextures = new List<CTexture>();
public SColorF Color;
@@ -69,8 +69,7 @@ namespace VocaluxeLib.Menu
{
_PartyModeID = partyModeID;
_ThemeLoaded = false;
_Theme = new SThemeBackground();
_Theme.SlideShowTextures = new List<string>();
_Theme = new SThemeBackground {SlideShowTextures = new List<string>()};
Color = new SColorF(0f, 0f, 0f, 1f);
}
@@ -102,11 +101,11 @@ namespace VocaluxeLib.Menu
_ThemeLoaded &= success;
}
string slideShow = "";
int i = 1;
while (xmlReader.ItemExists(item + "/SlideShow" + i))
{
string slideShow;
xmlReader.GetValue(item + "/SlideShow" + i, out slideShow, String.Empty);
if (slideShow != "")
_Theme.SlideShowTextures.Add(slideShow);
-2
View File
@@ -16,8 +16,6 @@
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Xml;
using VocaluxeLib.Songs;
-1
View File
@@ -19,7 +19,6 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using VocaluxeLib.Draw;
+56 -19
View File
@@ -15,11 +15,8 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using VocaluxeLib.PartyModes;
using VocaluxeLib.Draw;
using VocaluxeLib.Profile;
@@ -94,10 +91,7 @@ namespace VocaluxeLib.Menu
_NumPlayer = numPlayer;
_NumPlayerTeams = numPlayerTeams;
if (_NumTeams > 0)
_TeamList = new List<int>[_NumTeams];
else
_TeamList = new List<int>[1];
_TeamList = new List<int>[_NumTeams > 0 ? _NumTeams : 1];
if (_NumTeams != _NumPlayerTeams.Length)
_NumPlayerTeams = new int[_NumTeams];
@@ -126,7 +120,7 @@ namespace VocaluxeLib.Menu
{
//Handle left/right/up/down
_NameSelections[_NameSelection].HandleInput(keyEvent);
int numberPressed = -1;
int numPressed = -1;
bool resetSelection = false;
switch (keyEvent.Key)
{
@@ -157,20 +151,65 @@ namespace VocaluxeLib.Menu
case Keys.Back:
resetSelection = true;
break;
case Keys.D1:
case Keys.NumPad1:
numPressed = 1;
break;
case Keys.D2:
case Keys.NumPad2:
numPressed = 2;
break;
case Keys.D3:
case Keys.NumPad3:
numPressed = 3;
break;
case Keys.D4:
case Keys.NumPad4:
numPressed = 4;
break;
case Keys.D5:
case Keys.NumPad5:
numPressed = 5;
break;
case Keys.D6:
case Keys.NumPad6:
numPressed = 6;
break;
case Keys.D7:
case Keys.NumPad7:
numPressed = 7;
break;
case Keys.D8:
case Keys.NumPad8:
numPressed = 8;
break;
case Keys.D9:
case Keys.NumPad9:
numPressed = 9;
break;
}
if (numberPressed > 0 || resetSelection)
if (numPressed > 0 || resetSelection)
{
if (numberPressed == _SelectingFastPlayerNr || resetSelection)
if (numPressed == _SelectingFastPlayerNr || resetSelection)
{
//Reset all values
_SelectingFastPlayerNr = 0;
_SelectingKeyboardActive = false;
_NameSelections[_NameSelection].FastSelection(false, -1);
}
else if (numberPressed <= _NumPlayerTeams[_CurrentTeam])
else if (numPressed <= _NumPlayerTeams[_CurrentTeam])
{
_SelectingFastPlayerNr = numberPressed;
_NameSelections[_NameSelection].FastSelection(true, numberPressed);
_SelectingFastPlayerNr = numPressed;
_NameSelections[_NameSelection].FastSelection(true, numPressed);
}
_SelectingFast = false;
}
@@ -530,9 +569,7 @@ namespace VocaluxeLib.Menu
public SPartyNameOptions GetData()
{
SPartyNameOptions option = new SPartyNameOptions();
option.NumPlayerTeams = _NumPlayerTeams;
option.TeamList = _TeamList;
SPartyNameOptions option = new SPartyNameOptions {NumPlayerTeams = _NumPlayerTeams, TeamList = _TeamList};
return option;
}
@@ -692,7 +729,7 @@ namespace VocaluxeLib.Menu
{
if (_NumPlayerTeams[team] == _TeamList[team].Count && !_ChangePlayerNumDynamic)
return;
else if (_NumPlayerTeams[team] == _PartyMode.GetMaxPlayerPerTeam())
if (_NumPlayerTeams[team] == _PartyMode.GetMaxPlayerPerTeam())
return;
_NameSelections[_NameSelection].UseProfile(profileID);
@@ -707,8 +744,8 @@ namespace VocaluxeLib.Menu
{
List<int> ids = new List<int>();
ids.AddRange(_TeamList[t]);
for (int p = 0; p < ids.Count; p++)
_RemovePlayer(t, ids[p]);
foreach (int id in ids)
_RemovePlayer(t, id);
}
}
+1 -2
View File
@@ -94,7 +94,7 @@ namespace VocaluxeLib.Menu
private int _Player = -1;
private readonly List<int> _VisibleProfiles;
private List<int> _UsedProfiles;
private readonly List<int> _UsedProfiles;
private CStatic _PlayerSelector;
@@ -416,7 +416,6 @@ namespace VocaluxeLib.Menu
_Tiles[i].Avatar.Texture = CBase.Profiles.GetAvatar(_VisibleProfiles[i + offset * _Tiles.Count]);
_Tiles[i].Avatar.Color = new SColorF(1, 1, 1, 1);
_Tiles[i].Name.Text = CBase.Profiles.GetPlayerName(_VisibleProfiles[i + offset * _Tiles.Count]);
;
_Tiles[i].ProfileID = _VisibleProfiles[i + offset * _Tiles.Count];
}
else
+2 -3
View File
@@ -214,7 +214,8 @@ namespace VocaluxeLib.Menu.SongMenu
if (_SongMenu != null)
_SongMenu.OnHide();
switch (CBase.Config.GetSongMenuType())
_Type = CBase.Config.GetSongMenuType();
switch (_Type)
{
//case ESongMenu.TR_CONFIG_LIST:
// _SongMenu = new CSongMenuList();
@@ -231,8 +232,6 @@ namespace VocaluxeLib.Menu.SongMenu
// _SongMenu = new CSongMenuBook();
// break;
}
_Type = CBase.Config.GetSongMenuType();
}
}
}
@@ -17,7 +17,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;
using VocaluxeLib.Draw;
@@ -99,7 +98,7 @@ namespace VocaluxeLib.Menu.SongMenu
protected SThemeSongMenu _Theme;
private bool _ThemeLoaded;
private readonly Stopwatch _VideoFadeTimer = new Stopwatch();
private CFading _VideoFading;
private readonly List<int> _Streams = new List<int>();
protected CTexture _Vidtex;
@@ -388,12 +387,12 @@ namespace VocaluxeLib.Menu.SongMenu
{
if (_Vidtex != null)
{
if (_VideoFadeTimer.ElapsedMilliseconds <= 3000L)
_Vidtex.Color.A = _VideoFadeTimer.ElapsedMilliseconds / 3000f;
else
if (_VideoFading != null)
{
_Vidtex.Color.A = 1f;
_VideoFadeTimer.Stop();
bool finished;
_Vidtex.Color.A = _VideoFading.GetValue(out finished);
if (finished)
_VideoFading = null;
}
}
}
@@ -563,9 +562,7 @@ namespace VocaluxeLib.Menu.SongMenu
if (_PreviewVideoStream == -1)
return;
CBase.Video.Skip(_PreviewVideoStream, startposition, song.VideoGap);
_VideoFadeTimer.Stop();
_VideoFadeTimer.Reset();
_VideoFadeTimer.Start();
_VideoFading = new CFading(0f, 1f, 3f);
}
}
}
+20 -21
View File
@@ -67,11 +67,11 @@ namespace VocaluxeLib.Menu.SongMenu
{
set
{
base._PlaySong(value);
base._PreviewIdInternal = value;
_PlaySong(value);
_PreviewIdInternal = value;
_UpdatePreview();
}
get { return base._PreviewIdInternal; }
get { return _PreviewIdInternal; }
}
public override int GetActualSelection()
@@ -138,7 +138,7 @@ namespace VocaluxeLib.Menu.SongMenu
}
if (_Length < 0 && CBase.Sound.GetLength(_PreviewSongStream) > 0 && CBase.Songs.IsInCategory())
UpdateLength(CBase.Songs.GetVisibleSong(_PreviewId));
_UpdateLength(CBase.Songs.GetVisibleSong(_PreviewId));
}
private void _UpdatePreview()
@@ -181,7 +181,7 @@ namespace VocaluxeLib.Menu.SongMenu
_MedleyCalcIcon.Visible = song.Medley.Source == EDataSource.Calculated;
_MedleyTagIcon.Visible = song.Medley.Source == EDataSource.Tag;
UpdateLength(song);
_UpdateLength(song);
}
else
{
@@ -198,23 +198,22 @@ namespace VocaluxeLib.Menu.SongMenu
}
}
private void UpdateLength(CSong song)
private void _UpdateLength(CSong song)
{
if (song != null)
{
float time = CBase.Sound.GetLength(_PreviewSongStream);
if (Math.Abs(song.Finish) > 0.001)
time = song.Finish;
if (song == null)
return;
float time = CBase.Sound.GetLength(_PreviewSongStream);
if (Math.Abs(song.Finish) > 0.001)
time = song.Finish;
// The audiobackend is not yet ready to return the length
if (time > 0)
{
time -= song.Start;
var min = (int)Math.Floor(time / 60f);
var sec = (int)(time - min * 60f);
_SongLength.Text = min.ToString("00") + ":" + sec.ToString("00");
_Length = time;
}
// The audiobackend is ready to return the length
if (time > 0)
{
time -= song.Start;
var min = (int)Math.Floor(time / 60f);
var sec = (int)(time - min * 60f);
_SongLength.Text = min.ToString("00") + ":" + sec.ToString("00");
_Length = time;
}
}
@@ -556,7 +555,7 @@ namespace VocaluxeLib.Menu.SongMenu
public override void SetSelectedSong(int visibleSongNr)
{
base._PlaySong(visibleSongNr);
_PlaySong(visibleSongNr);
base.SetSelectedSong(visibleSongNr);
if (visibleSongNr >= 0 && visibleSongNr < CBase.Songs.GetNumSongsVisible())
+1 -1
View File
@@ -49,7 +49,7 @@ namespace VocaluxeLib.Profile
CBase.Drawing.RemoveTexture(ref Texture);
}
public string getFileName()
public string GetFileName()
{
return FileName;
}
+6 -5
View File
@@ -17,7 +17,6 @@
using System;
using System.IO;
using System.Text;
using System.Xml;
namespace VocaluxeLib.Profile
@@ -71,9 +70,11 @@ namespace VocaluxeLib.Profile
FileName = String.Empty;
}
public bool LoadProfile()
public bool LoadProfile(string pathName, string fileName)
{
return LoadProfile(FilePath, FileName);
FilePath = pathName;
FileName = fileName;
return LoadProfile();
}
public bool LoadProfile(string file)
@@ -81,10 +82,10 @@ namespace VocaluxeLib.Profile
FileName = Path.GetFileName(file);
FilePath = Path.GetDirectoryName(file);
return LoadProfile(FilePath, FileName);
return LoadProfile();
}
public bool LoadProfile(string pathName, string fileName)
public bool LoadProfile()
{
CXMLReader xmlReader = CXMLReader.OpenFile(Path.Combine(FilePath, FileName));
if (xmlReader == null)
+5 -11
View File
@@ -63,15 +63,10 @@ namespace VocaluxeLib.Songs
{
get
{
int min = int.MaxValue;
int max = int.MinValue;
foreach (T note in _Notes)
{
if (note.Tone < min)
min = note.Tone;
if (note.Tone > max)
max = note.Tone;
}
if (_Notes.Count == 0)
return 0;
int min = _Notes.Min(note => note.Tone);
int max = _Notes.Max(note => note.Tone);
return min - (max - min) / 4;
}
@@ -140,11 +135,10 @@ namespace VocaluxeLib.Songs
return false;
}
public bool IncLastNoteLength()
public void IncLastNoteLength()
{
if (_Notes.Count > 0)
_Notes[NoteCount - 1].Duration++;
return false;
}
public void DeleteAllNotes()
+1 -1
View File
@@ -97,7 +97,7 @@ namespace VocaluxeLib.Songs
public string MP3FileName = String.Empty;
public string CoverFileName = String.Empty;
public List<string> BackgroundFileNames = new List<string>();
public readonly List<string> BackgroundFileNames = new List<string>();
public string VideoFileName = String.Empty;
public EAspect VideoAspect = EAspect.Crop;
+1 -1
View File
@@ -81,7 +81,7 @@ namespace VocaluxeLib.Songs
msg = (error ? "Error: " : "Warning: ") + msg;
if (withLineNr)
msg += " in line #" + _LineNr;
CBase.Log.LogError(msg + " (" + Path.Combine(_Song.Folder, _Song.FileName) + ")");
CBase.Log.LogSongInfo(msg + " (" + Path.Combine(_Song.Folder, _Song.FileName) + ")");
}
private void _LogError(string msg, bool withLineNr = true)
+1
View File
@@ -41,6 +41,7 @@ namespace VocaluxeLib.Songs
/// <param name="duration"></param>
/// <param name="tone"></param>
/// <param name="hitNote"></param>
/// <param name="points"></param>
public CSungNote(int startBeat, int duration, int tone, CSongNote hitNote, double points) : this(startBeat, duration, tone)
{
HitNote = hitNote;
+1 -3
View File
@@ -205,15 +205,13 @@ namespace VocaluxeLib.Songs
public void UpdateTimings()
{
CSongNote lastNote;
if (_Lines.Count == 0)
return;
_Lines[0].StartBeat = -10000;
for (int i = 1; i < _Lines.Count; i++)
{
lastNote = _Lines[i - 1].LastNote;
CSongNote lastNote = _Lines[i - 1].LastNote;
CSongNote firstNote = _Lines[i].FirstNote;
if ((lastNote != null) && (firstNote != null))
+3 -5
View File
@@ -190,20 +190,18 @@ namespace VocaluxeLib
public int CurrentNote;
public int SongID;
public bool Medley;
public bool Duet;
public bool ShortSong;
public EGameMode GameMode;
public long DateTicks;
public bool SongFinished;
}
public struct SScores
public struct SDBScoreEntry
{
public string Name;
public int Score;
public string Date;
public EGameDifficulty Difficulty;
public int LineNr;
public int VoiceNr;
public int ID;
}
+1
View File
@@ -130,6 +130,7 @@
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<Compile Include="CFading.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="IBasic.cs" />
+144 -49
View File
@@ -15,6 +15,8 @@
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
#endregion
using System.Security.Authentication;
using System.Security.Principal;
using Security.Cryptography;
using Security.Cryptography.X509Certificates;
using System;
@@ -26,34 +28,64 @@ using NetFwTypeLib;
namespace WebserverInitalConfig
{
public static class CConfigHttpApi
public class CConfigHttpApi
{
// ReSharper disable InconsistentNaming
private const String CLSID_NetFwMgr = "{304CE942-6E39-40D8-943A-B913C40C9CD4}";
private const String CLSID_NetAuthApp = "{EC9846B3-2762-4A6B-A214-6ACB603462D2}";
private const String CLSID_NetOpenPort = "{0CA545C6-37AD-4A6C-BF92-9F7610067EF5}";
private const string _AppGUID = "{7baf41f1-48b7-42cb-b145-f815499cb48f}";
// ReSharper restore InconsistentNaming
public static void ReserveUrl(string networkString)
private readonly string _RuleName;
private readonly string _ExePath;
private readonly string _IP;
private readonly int _Port;
private readonly bool _IsTCP;
public CConfigHttpApi(string ruleName, string exePath, string ip, int port, bool isTCP)
{
_ExePath = exePath;
_Port = port;
_IsTCP = isTCP;
_IP = ip;
_RuleName = ruleName;
}
private static void _ReserveUrl(string networkString)
{
if (!IsAdministrator())
throw new AuthenticationException();
HttpApi.ReserveURL(networkString, "D:(A;;GX;;;S-1-1-0)");
}
public static void BindCert(string ip, int port, X509Certificate2 cert)
public void ReserveUrl()
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(ip), port);
if (HttpApi.QuerySslCertificateInfo(endpoint) != null)
HttpApi.DeleteCertificateBinding(endpoint);
HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid("{7baf41f1-48b7-42cb-b145-f815499cb48f}"));
_ReserveUrl("https://+:" + _Port + "/");
}
public static void AddCertToStore(X509Certificate2 cert)
private void _BindCert(X509Certificate cert)
{
IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(_IP), _Port);
HttpApi.SslCertificateInfo certificateInfo = HttpApi.QuerySslCertificateInfo(endpoint);
if (certificateInfo != null && !certificateInfo.Hash.SequenceEqual(cert.GetCertHash()))
{
if (!IsAdministrator())
throw new AuthenticationException();
HttpApi.DeleteCertificateBinding(endpoint);
HttpApi.BindCertificate(endpoint, cert.GetCertHash(), StoreName.My, new Guid(_AppGUID));
}
}
private static void _AddCertToStore(X509Certificate2 cert)
{
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
X509Certificate2Collection oldCerts = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName,
cert.SubjectName.Name, false);
// ReSharper disable AssignNullToNotNullAttribute
X509Certificate2Collection oldCerts = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, cert.SubjectName.Name, false);
// ReSharper restore AssignNullToNotNullAttribute
foreach (X509Certificate2 oldCert in oldCerts)
store.Remove(oldCert);
@@ -62,7 +94,25 @@ namespace WebserverInitalConfig
store.Close();
}
public static X509Certificate2 GetSelfSignedCert(string subjectName)
private static X509Certificate2 _GetCert(string name)
{
X509Certificate2 result = null;
X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
var name2 = new X500DistinguishedName(name);
// ReSharper disable AssignNullToNotNullAttribute
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, name2.Name, false);
// ReSharper restore AssignNullToNotNullAttribute
if (certs.Count > 0)
result = certs[0];
store.Close();
return result;
}
private X509Certificate2 _GetSelfSignedCert(string subjectName)
{
var keyParam = new CngKeyCreationParameters
{
@@ -91,58 +141,103 @@ namespace WebserverInitalConfig
byte[] rawData = key.CreateSelfSignedCertificate(param).Export(X509ContentType.Pfx, "");
var cert = new X509Certificate2(rawData, "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet)
{
FriendlyName = "Vocaluxe Server Certificate"
FriendlyName = _RuleName + " Server Certificate"
};
return cert;
}
private static void _AddFirewallRuleForProfile(INetFwProfile profile, string exePath, int port, bool isTCP)
public void CreateAndAddCert(string hostName)
{
bool isFirewallEnabled = profile.FirewallEnabled;
string certName = "CN=" + hostName + ", C=DE, O=" + _RuleName + ", OU=" + _RuleName + " Server";
if (!isFirewallEnabled)
return;
INetFwAuthorizedApplications applications = profile.AuthorizedApplications;
if (!(from INetFwAuthorizedApplication a in applications
where a.ProcessImageFileName == exePath
select a).Any())
X509Certificate2 cert = _GetCert(certName);
if (cert == null)
{
INetFwAuthorizedApplication application = (INetFwAuthorizedApplication)Activator.CreateInstance(
Type.GetTypeFromCLSID(new Guid(CLSID_NetAuthApp)));
application.Name = "Vocaluxe";
application.ProcessImageFileName = exePath;
application.Enabled = true;
application.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
applications.Add(application);
}
INetFwOpenPorts openPorts = profile.GloballyOpenPorts;
NET_FW_IP_PROTOCOL_ protocol = isTCP ? NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP;
if (!(from INetFwOpenPort p in openPorts
where (p.Port == port &&
(p.Protocol == protocol))
select p).Any())
{
INetFwOpenPort openPort = (INetFwOpenPort)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetOpenPort)));
openPort.Enabled = true;
openPort.Port = port;
openPort.Protocol = protocol;
openPort.Name = "Vocaluxe(" + port + ")";
openPort.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
openPorts.Add(openPort);
if (!IsAdministrator())
throw new AuthenticationException();
cert = _GetSelfSignedCert(certName);
_AddCertToStore(cert);
}
_BindCert(cert);
}
public static void AddFirewallRule(string exePath, int port, bool isTCP)
private bool _IsAppAuthorized(INetFwProfile profile)
{
if (!profile.FirewallEnabled)
return true;
return profile.AuthorizedApplications.Cast<INetFwAuthorizedApplication>().Any(a => a.ProcessImageFileName == _ExePath);
}
private bool _IsPortOpen(INetFwProfile profile)
{
NET_FW_IP_PROTOCOL_ protocol = _GetProtocol();
if (!profile.FirewallEnabled)
return true;
return profile.GloballyOpenPorts.Cast<INetFwOpenPort>().Any(p => p.Protocol == protocol && p.Port == _Port);
}
private NET_FW_IP_PROTOCOL_ _GetProtocol()
{
return _IsTCP ? NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP : NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_UDP;
}
private void _AddFirewallRuleForProfile(INetFwProfile profile)
{
bool isAppAuthorized = _IsAppAuthorized(profile);
bool isPortOpen = _IsPortOpen(profile);
if ((!isAppAuthorized || !isPortOpen) && !IsAdministrator())
throw new AuthenticationException();
if (!isAppAuthorized)
_AddAppToFirewall(profile);
if (!isPortOpen)
_AddPortToFirewall(profile);
}
private void _AddPortToFirewall(INetFwProfile profile)
{
INetFwOpenPort openPort = (INetFwOpenPort)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetOpenPort)));
openPort.Enabled = true;
openPort.Port = _Port;
openPort.Protocol = _GetProtocol();
openPort.Name = _RuleName + "(" + _Port + ")";
openPort.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
profile.GloballyOpenPorts.Add(openPort);
}
private void _AddAppToFirewall(INetFwProfile profile)
{
INetFwAuthorizedApplication application = (INetFwAuthorizedApplication)Activator.CreateInstance(
Type.GetTypeFromCLSID(new Guid(CLSID_NetAuthApp)));
application.Name = _RuleName;
application.ProcessImageFileName = _ExePath;
application.Enabled = true;
application.Scope = NET_FW_SCOPE_.NET_FW_SCOPE_ALL;
profile.AuthorizedApplications.Add(application);
}
public static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
// ReSharper disable AssignNullToNotNullAttribute
WindowsPrincipal principal = new WindowsPrincipal(identity);
// ReSharper restore AssignNullToNotNullAttribute
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
public void AddFirewallRule()
{
INetFwMgr manage = (INetFwMgr)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID_NetFwMgr)));
//AddFirewallRuleForProfile(manage.LocalPolicy.CurrentProfile, exePath, port, isTCP);
//_AddFirewallRuleForProfile(manage.LocalPolicy.CurrentProfile);
//if (manage.CurrentProfileType != NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD)
//Add to Home/Work(Private) and current net
//TODO: This somewhow adds 2 entries each instead of only one that is activated for Home/Work and public nets
_AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD), exePath, port, isTCP);
_AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_CURRENT), exePath, port, isTCP);
_AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_STANDARD));
_AddFirewallRuleForProfile(manage.LocalPolicy.GetProfileByType(NET_FW_PROFILE_TYPE_.NET_FW_PROFILE_CURRENT));
}
/*public static X509Certificate2 getCert(string subject)
-3
View File
@@ -18,13 +18,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
namespace WebserverInitalConfig
{
+43 -15
View File
@@ -16,34 +16,62 @@
#endregion
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Security.Authentication;
namespace WebserverInitalConfig
{
class Program
static class CProgram
{
// ReSharper disable InconsistentNaming
private static void Main(string[] args)
// ReSharper restore InconsistentNaming
{
if (args.Length != 2)
int port;
if (args.Length < 2 || !int.TryParse(args[0], out port))
{
Console.WriteLine("Usage: VocaluxeServerConfig port isHttps");
Environment.Exit(-1);
}
CConfigHttpApi.AddFirewallRule(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vocaluxe.exe"), Int32.Parse(args[0]), true);
if (args[1].ToLower() == "true")
{
string hostname = Dns.GetHostName();
X509Certificate2 cert = CConfigHttpApi.GetSelfSignedCert("CN=" + hostname + " C=DE O=Vocaluxe OU=Vocaluxe Server");
CConfigHttpApi.AddCertToStore(cert);
CConfigHttpApi.BindCert("0.0.0.0", Int32.Parse(args[0]), cert);
CConfigHttpApi.ReserveUrl("https://+:" + args[0] + "/");
}
else
CConfigHttpApi.ReserveUrl("http://+:" + args[0] + "/");
{
CConfigHttpApi config = new CConfigHttpApi("Vocaluxe", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Vocaluxe.exe"), "0.0.0.0", port, true);
try
{
config.AddFirewallRule();
if (args[1].ToLower() == "true")
config.CreateAndAddCert(Dns.GetHostName());
if ((args.Length >= 3 && args[2] == "reserve") || CConfigHttpApi.IsAdministrator())
config.ReserveUrl();
}
catch (AuthenticationException)
{
ProcessStartInfo proc = new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = Environment.CurrentDirectory,
FileName = Process.GetCurrentProcess().MainModule.FileName,
Arguments = args[0] + " " + args[1],
Verb = "runas",
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
};
try
{
Process.Start(proc);
}
catch
{
// The user refused the elevation.
// Do nothing and return directly ...
Environment.Exit(-1);
}
}
}
}
}
}
@@ -16,7 +16,6 @@
#endregion
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
@@ -32,9 +32,6 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Vocaluxe.ico</ApplicationIcon>
</PropertyGroup>