private async void Window_PreviewKeyDown(object sender, KeyEventArgs e) { var key = e.Key == Key.System ? e.SystemKey : e.Key; ApplyKeyboardModifiers(); if (!tasklist.SearchBox.TextBox.IsFocused) { if (AP.IsMouseOver && !AP.IsKeyboardFocusWithin) { e.Handled = true; switch (key) { case Key.Space: if (Keyboard.Modifiers == ModifierKeys.Control) { tasklist.FILEList.ScrollIntoView(AP.CurrentPlaying); } else { if (AP.Player.State == MediaStates.Stopped || AP.Player.State == MediaStates.NothingSpecial) { await PlayFile(tasklist.FILEList.SelectedItem as Fichier, null); } else { await AP.PlayPause(); } } break; case Key.S: if (Keyboard.Modifiers == ModifierKeys.Shift) { await VGMStream.DeleteTempFilesIfNotUsed(); GC.Collect(); } else { await CancelAndStop(); } break; case Key.PageDown: await NextWithRandom(); break; case Key.PageUp: await PreviousWithRandom(); break; case Key.Insert: tasklist.OpenFileDialog((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control, (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt); break; case Key.Delete: switch (Keyboard.Modifiers) { case ModifierKeys.Control: tasklist.RemoveInvalidItems(); break; case ModifierKeys.Shift: tasklist.RemoveAll(); break; case ModifierKeys.Alt: tasklist.RemoveDFiles(); break; case ModifierKeys.Control | ModifierKeys.Alt: tasklist.RemoveSNFiles(); break; default: tasklist.RemoveSelectedItems(); break; } break; case Key.Left: await AP.PositionMinus(); break; case Key.Right: await AP.PositionPlus(); break; default: goto NoMouseOver; } } if (tasklist.IsMouseOver && !tasklist.IsKeyboardFocusWithin) { switch (key) { case Key.F: if (Keyboard.Modifiers == ModifierKeys.Control) { e.Handled = true; if (tasklist.SearchBox.Visibility == Visibility.Visible) { tasklist.SearchBox.TextBox.Focus(); } else { tasklist.SearchBox.Visibility = Visibility.Visible; } } break; case Key.C: if (Keyboard.Modifiers == ModifierKeys.Control) { tasklist.CopySelectedFiles(); } break; case Key.X: if (Keyboard.Modifiers == ModifierKeys.Control) { tasklist.CutSelectedFiles(); } break; case Key.V: if (Keyboard.Modifiers == ModifierKeys.Control) { tasklist.PasteFiles(); } break; } if (!tasklist.IsKeyboardFocusWithin) { tasklist.FILEList_PreviewKeyDown(sender, e); } } if (tasklist.IsMouseOver && !AP.IsKeyboardFocusWithin) { switch (key) { case Key.Space: e.Handled = true; if (Keyboard.Modifiers == ModifierKeys.Control) { tasklist.FILEList.ScrollIntoView(AP.CurrentPlaying); } else { if (AP.Player.State == MediaStates.Stopped || AP.Player.State == MediaStates.NothingSpecial) { await PlayFile(tasklist.FILEList.SelectedItem as Fichier, null); } else { await AP.PlayPause(); } } break; case Key.S: if (Keyboard.Modifiers == ModifierKeys.Shift) { await VGMStream.DeleteTempFilesIfNotUsed(); GC.Collect(); } else { await CancelAndStop(); } break; case Key.PageDown: e.Handled = true; await NextWithRandom(); break; case Key.PageUp: e.Handled = true; await PreviousWithRandom(); break; } } } NoMouseOver: switch (key) { case Key.Play: if (AP.Player.State == MediaStates.Stopped || AP.Player.State == MediaStates.NothingSpecial) { await PlayFile(tasklist.FILEList.SelectedItem as Fichier, null); } else { await AP.Play(); } break; case Key.Pause: await AP.Pause(); break; case Key.MediaPlayPause: if (AP.Player.State == MediaStates.Stopped || AP.Player.State == MediaStates.NothingSpecial) { await PlayFile(tasklist.FILEList.SelectedItem as Fichier, null); } else { await AP.PlayPause(); } break; case Key.MediaStop: await CancelAndStop(); break; case Key.MediaNextTrack: await NextWithRandom(); break; case Key.MediaPreviousTrack: await PreviousWithRandom(); break; case Key.B: if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift)) { e.Handled = true; StatusBar.Display = !StatusBar.Display; Settings.SettingsData["StatusBar"]["Display"] = StatusBar.Display.ToString(); } break; case Key.P: if (Keyboard.Modifiers == ModifierKeys.Control) { OpenSettingsWindow(); } break; case Key.O: switch (Keyboard.Modifiers) { case ModifierKeys.Control | ModifierKeys.Shift: tasklist.OpenFileDialog(true, false); break; case ModifierKeys.Control: tasklist.OpenFileDialog(false, false); break; case ModifierKeys.Control | ModifierKeys.Alt | ModifierKeys.Shift: tasklist.OpenFileDialog(true, true); break; case ModifierKeys.Control | ModifierKeys.Alt: tasklist.OpenFileDialog(false, true); break; } break; case Key.D: switch (Keyboard.Modifiers) { case ModifierKeys.Control | ModifierKeys.Alt: if (await VGMStream.DownloadVLC()) { MessageBox.Show(App.Str("WW_VLCDownloaded"), string.Empty, MessageBoxButton.OK, MessageBoxImage.Information); } break; case ModifierKeys.Control: await VGMStream.DownloadVGMStream(); break; } break; case Key.F5: StartButton_Click(StartButton, new RoutedEventArgs()); break; #if DEBUG case Key.X: if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Alt)) { /*switch (App.CurrentCulture.ToString()) * { * case "fr-FR": * App.SetLanguage("en-US"); * break; * case "en-US": * App.SetLanguage("fr-FR"); * break; * }*/ } break; #endif } }
/// <summary> /// Convertit un fichier et lance le suivant dans <see cref='FilesToConvert'/>. /// </summary> /// <param name="fichier">Le fichier à convertir.</param> /// <param name="cancellationToken">Jeton d'annulation qui peut être utilisé par d'autres objets ou threads pour être informés de l'annulation.</param> /// <returns>true si la conversion a réussi; sinon false.</returns> public static async Task <string[]> ConvertFile(Fichier fichier, bool finalize = true, CancellationToken cancellationToken = default, PauseToken pauseToken = default) { bool success = false; IEnumerable <string> filesToDelete = null; try { ConversionCount++; await pauseToken.WaitWhilePausedAsync(); if (cancellationToken.IsCancellationRequested || !File.Exists(fichier.Path)) { return(null); } fichier.OriginalState = "FSTATE_Conversion"; var(dspFileNames, channelsCount) = await GetDSPFiles(fichier.Path, VGMStreamProcessTypes.Conversion, 0, cancellationToken, pauseToken); if ((filesToDelete = dspFileNames) == null) { return(null); } var wavFileNames = (await dspFileNames.SelectAsync(dspFile => VGMStream.CreateTempFile("wav", VGMStreamProcessTypes.Conversion), cancellationToken)).ToArray(); filesToDelete = dspFileNames.Concat(wavFileNames); var vgmstreamTmpInfos = new ProcessStartInfo[channelsCount]; var vgmstreamTmpProcess = new Process[channelsCount]; await pauseToken.WaitWhilePausedAsync(); if (cancellationToken.IsCancellationRequested || !File.Exists(App.VGMStreamPath) && !await App.AskVGMStream()) { return(null); //Check VGMStream } for (int i = 0; i < channelsCount && !cancellationToken.IsCancellationRequested; i++) { await Task.Run(() => { pauseToken.WaitWhilePausedAsync(); vgmstreamTmpInfos[i] = VGMStream.StartInfo(dspFileNames[i], wavFileNames[i], fichier.LoopCount, fichier.FadeOut, fichier.FadeDelay, fichier.FadeTime, fichier.StartEndLoop); vgmstreamTmpProcess[i] = Process.Start(vgmstreamTmpInfos[i]); VGMStream.RunningProcess.Add(vgmstreamTmpProcess[i], VGMStreamProcessTypes.Conversion); }); } for (int i = 0; i < vgmstreamTmpProcess.Length; i++) { await vgmstreamTmpProcess[i].WaitForExitAsync(cancellationToken); if (vgmstreamTmpProcess[i].ExitCode != 0) { return(null); } } if (cancellationToken.IsCancellationRequested) { return(null); } try { await Task.Run(() => { var wfrs = wavFileNames.Select(file => new WaveFileReader(file)).ToArray(); var waveProvider = new MultiplexingWaveProvider(wfrs); WaveFileWriter.CreateWaveFile(fichier.FinalDestination, waveProvider); foreach (var wfr in wfrs) { wfr.Close(); } }, cancellationToken); await pauseToken.WaitWhilePausedAsync(); if (!cancellationToken.IsCancellationRequested) { success = true; var data = await vgmstreamTmpProcess[0].StandardOutput.ReadAllLinesAsync().WithCancellation(cancellationToken); var indexOfPath = data.IndexOf(data.FirstOrDefault(s => s.Contains(dspFileNames[0]))); var indexOfChannels = data.IndexOf(data.FirstOrDefault(s => s.Contains("channels"))); var indexOfFormat = data.IndexOf(data.FirstOrDefault(s => s.Contains("metadata from"))); var indexOfBitrate = data.IndexOf(data.FirstOrDefault(s => s.Contains("bitrate"))); data[indexOfPath] = data[indexOfPath].Replace(dspFileNames[0], fichier.Path); data[indexOfChannels] = data[indexOfChannels].Replace("1", channelsCount.ToString()); data[indexOfFormat] = data[indexOfFormat].Replace("Standard Nintendo DSP header", "Retro Studios DKCTF CSMP"); var brp = data[indexOfBitrate].Split(':'); if (brp.Length == 2) { var brs = brp[1].Replace("kbps", string.Empty); var br = brs.ToInt(); if (br != null) { var bitrate = br * channelsCount; data[indexOfBitrate] = data[indexOfBitrate].Replace(br.ToString(), bitrate.ToString()); } } return(data); } else { return(null); } } catch { return(null); } } catch (OperationCanceledException) { return(null); } finally { await VGMStream.DeleteTempFilesByName(filesToDelete); if (success) { fichier.OriginalState = "FSTATE_Completed"; } else if (!cancellationToken.IsCancellationRequested && finalize) { fichier.SetInvalid(); } ConversionCount--; } }
/// <summary> /// À partir d'un nom de fichier, obtient un fichier analysé uniquement s'il possède l'en-tête RFRM CSMP. /// </summary> /// <param name="fileName">Nom du fichier.</param> /// <param name="outData">Données complémentaires pour le fichier.</param> /// <param name="cancellationToken">Jeton d'annulation qui peut être utilisé par d'autres objets ou threads pour être informés de l'annulation.</param> /// <returns>Le fichier analysé.</returns> public static async Task <Fichier> GetFile(string fileName, FichierOutData outData = default, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested || !File.Exists(fileName)) { return(null); } IEnumerable <string> filesToDelete = null; try { ScanningCount++; var(dspFileNames, channelsCount) = await GetDSPFiles(fileName, VGMStreamProcessTypes.Metadata, 1, cancellationToken); if ((filesToDelete = dspFileNames) == null) { return(null); } Process vgmstreamprocess = new Process() { StartInfo = VGMStream.StartInfo(dspFileNames[0], VGMStreamProcessTypes.Metadata) }; VGMStream.RunningProcess.Add(vgmstreamprocess, VGMStreamProcessTypes.Metadata); cancellationToken.Register(() => { vgmstreamprocess.TryKill(); if (VGMStream.RunningProcess.ContainsKey(vgmstreamprocess)) { VGMStream.RunningProcess.Remove(vgmstreamprocess); } }); TryResult StartResult = await vgmstreamprocess.TryStartAsync(cancellationToken); //Start if (!StartResult.Result) //N'a pas pu être démarré { if (!(StartResult.Exception is OperationCanceledException)) { MessageBox.Show(StartResult.Exception.Message, App.Str("TT_Error"), MessageBoxButton.OK, MessageBoxImage.Error); } return(null); } await vgmstreamprocess.WaitForExitAsync(cancellationToken); //WaitForExit if (VGMStream.RunningProcess.ContainsKey(vgmstreamprocess)) { VGMStream.RunningProcess.Remove(vgmstreamprocess); } if (cancellationToken.IsCancellationRequested) { return(null); } string[] s = vgmstreamprocess.StandardOutput.ReadAllLines(); if (s.IsNullOrEmpty()) { return(null); } var fichier = VGMStream.GetFile(s, outData, false, false); if (cancellationToken.IsCancellationRequested) { return(null); } else if (fichier.Invalid) { return(fichier); } else { fichier.Path = fileName; fichier.OriginalFormat = "Retro Studios DKCTF CSMP"; fichier.Channels = channelsCount; fichier.Bitrate *= channelsCount; return(fichier); } } catch (OperationCanceledException) { return(null); } catch (Exception ex) { MessageBox.Show(ex.Message, App.Str("TT_Error"), MessageBoxButton.OK, MessageBoxImage.Error); return(null); } finally { if (!cancellationToken.IsCancellationRequested) { await VGMStream.DeleteTempFilesByName(filesToDelete); } ScanningCount--; } }
/// <summary> /// Obtient le nom du fichier audio au format WAV à partir d'un fichier RFRM CSMP. /// </summary> /// <param name="fichier">Le fichier à décoder.</param> /// <param name="Out">true si la sortie doit être lue; false si l'entrée doit être lue.</param> /// <param name="cancellationToken">Jeton d'annulation qui peut être utilisé par d'autres objets ou threads pour être informés de l'annulation.</param> /// <returns>Le Stream contenant les données audio.</returns> public static async Task <Stream> GetStream(Fichier fichier, bool Out = false, CancellationToken cancellationToken = default) { if (cancellationToken.IsCancellationRequested || !File.Exists(fichier.Path)) { return(null); } IEnumerable <string> filesToDelete = null; string fn = await VGMStream.CreateTempFileAsync("wav", VGMStreamProcessTypes.Streaming); //Nom du fichier temporaire try { StreamingCount++; var(dspFileNames, channelsCount) = await GetDSPFiles(fichier.Path, VGMStreamProcessTypes.Streaming, 0, cancellationToken); if ((filesToDelete = dspFileNames) == null) { return(null); } var wavFileNames = (await dspFileNames.SelectAsync(dspFile => VGMStream.CreateTempFile("wav", VGMStreamProcessTypes.Streaming), cancellationToken)).ToArray(); filesToDelete = dspFileNames.Concat(wavFileNames); var vgmstreamTmpInfos = new ProcessStartInfo[channelsCount]; var vgmstreamTmpProcess = new Process[channelsCount]; if (cancellationToken.IsCancellationRequested || !File.Exists(App.VGMStreamPath) && !await App.AskVGMStream()) { return(null); //Check VGMStream } for (int i = 0; i < channelsCount && !cancellationToken.IsCancellationRequested; i++) { await Task.Run(() => { vgmstreamTmpInfos[i] = Out ? VGMStream.StartInfo(dspFileNames[i], wavFileNames[i], fichier.LoopCount, fichier.FadeOut, fichier.FadeDelay, fichier.FadeTime, fichier.StartEndLoop) : VGMStream.StartInfo(dspFileNames[i], wavFileNames[i], 1, false); vgmstreamTmpProcess[i] = Process.Start(vgmstreamTmpInfos[i]); VGMStream.RunningProcess.Add(vgmstreamTmpProcess[i], VGMStreamProcessTypes.Streaming); }); } cancellationToken.Register(() => { foreach (Process process in vgmstreamTmpProcess) { process.TryKill(); if (VGMStream.RunningProcess.ContainsKey(process)) { VGMStream.RunningProcess.Remove(process); } } }); for (int i = 0; i < vgmstreamTmpProcess.Length; i++) { await vgmstreamTmpProcess[i].WaitForExitAsync(cancellationToken); if (vgmstreamTmpProcess[i].ExitCode != 0) { return(null); } } if (cancellationToken.IsCancellationRequested) { return(null); } try { await Task.Run(() => { var wfrs = wavFileNames.Select(file => new WaveFileReader(file)).ToArray(); var waveProvider = new MultiplexingWaveProvider(wfrs); WaveFileWriter.CreateWaveFile(fn, waveProvider); foreach (var wfr in wfrs) { wfr.Close(); } }, cancellationToken); return(cancellationToken.IsCancellationRequested ? null : File.OpenRead(fn)); } catch (OperationCanceledException) { return(null); } catch { fichier.SetInvalid(); return(null); } } catch (OperationCanceledException) { return(null); } catch (Exception ex) { MessageBox.Show(ex.Message, App.Str("TT_Error"), MessageBoxButton.OK, MessageBoxImage.Error); return(null); } finally { if (!cancellationToken.IsCancellationRequested) { await VGMStream.DeleteTempFilesByName(filesToDelete); } StreamingCount--; } }