Index: Configuration/Sections/Music.cs =================================================================== --- Configuration/Sections/Music.cs (revision 28123) +++ Configuration/Sections/Music.cs (working copy) @@ -1811,8 +1811,7 @@ BassVis.BASSVIS_Quit(_visParam); } _visParam = new BASSVIS_PARAM(BASSVISKind.BASSVISKIND_WINAMP); - BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_WINAMP, System.Diagnostics.Process.GetCurrentProcess().Handle, - MediaPortal.GUI.Library.GUIGraphicsContext.form.Handle); + BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_WINAMP, MediaPortal.GUI.Library.GUIGraphicsContext.form.Handle); int tmpVis = BassVis.BASSVIS_GetPluginHandle(BASSVISKind.BASSVISKIND_WINAMP, VizPluginInfo.FilePath); if (tmpVis != 0) { Index: Core/MusicPlayer/BASS/BassAudio.cs =================================================================== --- Core/MusicPlayer/BASS/BassAudio.cs (revision 28123) +++ Core/MusicPlayer/BASS/BassAudio.cs (working copy) @@ -1537,8 +1537,6 @@ /// /// Return the BASS Stream to be used for Visualisation purposes. /// We will extract the WAVE and FFT data to be provided to the Visualisation Plugins - /// In case of Mixer active, we need to return the Mixer Stream. - /// In all other cases the current active stream is used. /// /// internal int GetCurrentVizStream() @@ -1548,20 +1546,12 @@ return -1; } - // In case od ASIO return the clone of the stream, because for a decoding channel, we can't get data from the original stream - if (_useASIO) + if (_streamcopy != null) { return _streamcopy.Stream; } - if (_Mixing) - { - return _mixer; - } - else - { - return GetCurrentStream(); - } + return -1; } /// @@ -2496,6 +2486,29 @@ Enum.GetName(typeof (BASSError), Bass.BASS_ErrorGetCode())); } + // For Visualisations, we take a clone of the existing stream + if (VizManager.CurrentVisualizationType != VisualizationInfo.PluginType.None) + { + Log.Debug("Cloning Music Stream to serve Visualisation"); + // In order to provide data for visualisation we need to clone the stream + _streamcopy = new StreamCopy(); + _streamcopy.ChannelHandle = stream; + // Use a default 16-bit channel, so that we don't have Problems with the Vis + _streamcopy.StreamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_DEFAULT; + try + { + _streamcopy.Start(); // start the cloned stream + } + catch (Exception) + { + Log.Error("Captured an error on StreamCopy start"); + } + } + else + { + _streamcopy = null; + } + bool playbackStarted = false; if (_Mixing) { @@ -2515,13 +2528,7 @@ // Get some information about the stream BASS_CHANNELINFO info = new BASS_CHANNELINFO(); Bass.BASS_ChannelGetInfo(stream, info); - - // In order to provide data for visualisation we need to clone the stream - _streamcopy = new StreamCopy(); - _streamcopy.ChannelHandle = stream; - _streamcopy.StreamFlags = BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT; - // decode the channel, so that we have a Streamcopy - + _asioHandler.Pan = _asioBalance; _asioHandler.Volume = (float)_StreamVolume / 100f; @@ -2530,15 +2537,6 @@ // try to set the device rate too (saves resampling) BassAsio.BASS_ASIO_SetRate((double)info.freq); - try - { - _streamcopy.Start(); // start the cloned stream - } - catch (Exception) - { - Log.Error("Captured an error on StreamCopy start"); - } - if (BassAsio.BASS_ASIO_IsStarted()) { setCueTrackEndPosition(stream); Index: Core/MusicPlayer/Visualization/SoniqueViz.cs =================================================================== --- Core/MusicPlayer/Visualization/SoniqueViz.cs (revision 28123) +++ Core/MusicPlayer/Visualization/SoniqueViz.cs (working copy) @@ -183,7 +183,15 @@ { try { - BassVis.BASSVIS_Free(_visParam, ref _baseVisParam); + int counter = 0; + + bool bFree = BassVis.BASSVIS_Free(_visParam); + while ((!bFree) && (counter <= 250)) + { + bFree = BassVis.BASSVIS_IsFree(_visParam); + System.Windows.Forms.Application.DoEvents(); + counter++; + } } catch (AccessViolationException) {} Index: Core/MusicPlayer/Visualization/VisualizationBase.cs =================================================================== --- Core/MusicPlayer/Visualization/VisualizationBase.cs (revision 28123) +++ Core/MusicPlayer/Visualization/VisualizationBase.cs (working copy) @@ -109,12 +109,12 @@ switch (VizPluginInfo.VisualizationType) { case VisualizationInfo.PluginType.Sonique: - BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_SONIQUE, hInstance, GUIGraphicsContext.form.Handle); + BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_SONIQUE, GUIGraphicsContext.form.Handle); _visParam = new BASSVIS_PARAM(BASSVISKind.BASSVISKIND_SONIQUE); break; case VisualizationInfo.PluginType.Winamp: - BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_WINAMP, hInstance, GUIGraphicsContext.form.Handle); + BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_WINAMP, GUIGraphicsContext.form.Handle); _visParam = new BASSVIS_PARAM(BASSVISKind.BASSVISKIND_WINAMP); break; } Index: Core/MusicPlayer/Visualization/VisualizationManager.cs =================================================================== --- Core/MusicPlayer/Visualization/VisualizationManager.cs (revision 28123) +++ Core/MusicPlayer/Visualization/VisualizationManager.cs (working copy) @@ -47,7 +47,6 @@ private int _TargetFPS = 20; private BASSVIS_PARAM _visParam = null; - private BASSVIS_PARAM _mBase = null; #endregion @@ -267,9 +266,6 @@ /// public List GetVisualizationPluginsInfo() { - // Get a handle to our program instance - IntPtr hInstance = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]); - _VisualizationPluginsInfo.Clear(); try { @@ -322,7 +318,7 @@ if (soniqueVisPaths != null && soniqueVisPaths[0] != "") { - BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_SONIQUE, hInstance, VizRenderWindow.Handle); + BassVis.BASSVIS_Init(BASSVISKind.BASSVISKIND_SONIQUE, VizRenderWindow.Handle); _visParam = new BASSVIS_PARAM(BASSVISKind.BASSVISKIND_SONIQUE); for (int i = 0; i < soniqueVisPaths.Length; i++) { @@ -334,13 +330,19 @@ if (_visParam.VisHandle != 0) { - BassVis.BASSVIS_Free(_visParam, ref _mBase); - _mBase = new BASSVIS_PARAM(_visParam.Kind); - _visParam.VisHandle = _mBase.VisHandle; + int counter = 0; + + bool bFree = BassVis.BASSVIS_Free(_visParam); + while ((!bFree) && (counter <= 250)) + { + bFree = BassVis.BASSVIS_IsFree(_visParam); + System.Windows.Forms.Application.DoEvents(); + counter++; + } + _visParam.VisHandle = 0; } BassVis.BASSVIS_ExecutePlugin(visExec, _visParam); - _mBase = new BASSVIS_PARAM(_visParam.Kind, _visParam.VisHandle); string pluginname = BassVis.BASSVIS_GetPluginName(_visParam); if (pluginname != null) Index: Core/MusicPlayer/Visualization/VisualizationWindow.cs =================================================================== --- Core/MusicPlayer/Visualization/VisualizationWindow.cs (revision 28123) +++ Core/MusicPlayer/Visualization/VisualizationWindow.cs (working copy) @@ -1934,29 +1934,32 @@ } DialogWindowIsActive = false; - using (Graphics g = Graphics.FromHwnd(Handle)) + if (VisualizationRunning) { - int sleepMS = RenderVisualization(g); - - if (sleepMS < 0) + using (Graphics g = Graphics.FromHwnd(Handle)) { - sleepMS = 0; - } + int sleepMS = RenderVisualization(g); - if (Viz.IsWinampVis()) - { - continue; - } + if (sleepMS < 0) + { + sleepMS = 0; + } - // Is it a Soundspectrum Viz, then we use, what their render returned in sleepMS - if (IsSoundSpectrumViz) - { - Thread.Sleep(sleepMS); + if (Viz.IsWinampVis()) + { + continue; + } + + // Is it a Soundspectrum Viz, then we use, what their render returned in sleepMS + if (IsSoundSpectrumViz) + { + Thread.Sleep(sleepMS); + } + else + { + Thread.Sleep(VisualizationRenderInterval); + } } - else - { - Thread.Sleep(VisualizationRenderInterval); - } } } } Index: Core/MusicPlayer/Visualization/VisualizationWindow.Designer.cs =================================================================== --- Core/MusicPlayer/Visualization/VisualizationWindow.Designer.cs (revision 28123) +++ Core/MusicPlayer/Visualization/VisualizationWindow.Designer.cs (working copy) @@ -17,6 +17,9 @@ { components.Dispose(); } + // Needed for RunRenderThread to prevent errors while disposing + VisualizationRunning = false; + base.Dispose(disposing); } Index: Core/MusicPlayer/Visualization/WinampViz.cs =================================================================== --- Core/MusicPlayer/Visualization/WinampViz.cs (revision 28123) +++ Core/MusicPlayer/Visualization/WinampViz.cs (working copy) @@ -25,6 +25,7 @@ using MediaPortal.Player; using MediaPortal.TagReader; using MediaPortal.Util; +using MediaPortal.Playlists; using BassVis_Api; namespace MediaPortal.Visualization @@ -34,14 +35,18 @@ #region Variables private BASSVIS_INFO _mediaInfo = null; + private BassVis.BASSVISSTATE _visCallback; private bool RenderStarted = false; private bool firstRun = true; private IntPtr hwndChild; // Handle to the Winamp Child Window. + private BASSVIS_PARAM _tmpVisParam = null; private MusicTag trackTag = null; private string _songTitle = " "; // Title of the song played + private int _playlistTitlePos; + private PlayListPlayer _playlistPlayer = null; #endregion @@ -128,6 +133,29 @@ #endregion + #region BASSVIS_StateCallback() + + public void BASSVIS_StateCallback(BASSVIS_PLAYSTATE NewState) + { + //CallBack PlayState for Winamp only + switch (NewState) + { + + case BASSVIS_PLAYSTATE.SetPlaylistTitle: + + BassVis.BASSVIS_SetPlayState(_visParam, BASSVIS_PLAYSTATE.SetPlaylistTitle, -1, _songTitle); + + break; + case BASSVIS_PLAYSTATE.GetPlaylistTitlePos: + + _playlistTitlePos = BassVis.BASSVIS_SetPlayState(_visParam, BASSVIS_PLAYSTATE.GetPlaylistTitlePos); + break; + + } + } + + #endregion + #region Overloads public override bool InitializePreview() @@ -155,10 +183,13 @@ // Set Song information, so that the plugin can display it if (trackTag != null && Bass != null) { + _playlistPlayer = PlayListPlayer.SingletonPlayer; + PlayListItem curPlaylistItem = _playlistPlayer.GetCurrentItem(); + _mediaInfo.Position = (int)Bass.CurrentPosition; _mediaInfo.Duration = (int)Bass.Duration; _mediaInfo.PlaylistLen = 1; - _mediaInfo.PlaylistPos = 1; + _mediaInfo.PlaylistPos = _playlistPlayer.CurrentPlaylistPos; } else { @@ -209,7 +240,15 @@ if (_visParam.VisHandle != 0) { BassVis.BASSVIS_SetPlayState(_visParam, BASSVIS_PLAYSTATE.Stop); - BassVis.BASSVIS_Free(_visParam, ref _baseVisParam); + int counter = 0; + + bool bFree = BassVis.BASSVIS_Free(_visParam); + while ((!bFree) && (counter <= 250)) + { + bFree = BassVis.BASSVIS_IsFree(_visParam); + System.Windows.Forms.Application.DoEvents(); + counter++; + } _visParam.VisHandle = 0; } @@ -246,11 +285,11 @@ // Do a move of the Winamp Viz if (_visParam.VisHandle != 0) { - hwndChild = Win32API.GetWindow(VisualizationWindow.Handle, Win32API.ShowWindowFlags.Show); - if (hwndChild != IntPtr.Zero) - { - Win32API.MoveWindow(hwndChild, 0, 0, newSize.Width, newSize.Height, true); - } + // Hide the Viswindow, so that we don't see it, while moving + Win32API.ShowWindow(hwndChild, Win32API.ShowWindowFlags.Hide); + _tmpVisParam = new BASSVIS_PARAM(BASSVISKind.BASSVISKIND_WINAMP); + _tmpVisParam.VisGenWinHandle = VisualizationWindow.Handle; + BassVis.BASSVIS_Resize(_tmpVisParam, 0, 0, newSize.Width, newSize.Height); } return true; } @@ -281,36 +320,36 @@ if (_visParam.VisHandle != 0) { - BassVis.BASSVIS_Free(_visParam, ref _baseVisParam); + RenderStarted = false; + + int counter = 0; + + bool bFree = BassVis.BASSVIS_Free(_visParam); + while ((!bFree) && (counter <= 250)) + { + bFree = BassVis.BASSVIS_IsFree(_visParam); + System.Windows.Forms.Application.DoEvents(); + counter++; + } _visParam.VisHandle = 0; - RenderStarted = false; } - // Set Dummy Information for the plugin, before creating it - _mediaInfo.SongTitle = ""; - _mediaInfo.SongFile = ""; - _mediaInfo.Position = 0; - _mediaInfo.Duration = 0; - _mediaInfo.PlaylistPos = 0; - _mediaInfo.PlaylistLen = 0; - BassVis.BASSVIS_SetInfo(_visParam, _mediaInfo); - try { + //Remove existing CallBacks + BassVis.BASSVIS_WINAMPRemoveCallback(); + // Create the Visualisation BASSVIS_EXEC visExec = new BASSVIS_EXEC(VizPluginInfo.FilePath); visExec.AMP_ModuleIndex = VizPluginInfo.PresetIndex; visExec.AMP_UseOwnW1 = 1; visExec.AMP_UseOwnW2 = 1; BassVis.BASSVIS_ExecutePlugin(visExec, _visParam); - if (_visParam.VisGenWinHandle != IntPtr.Zero) + if (_visParam.VisHandle != 0) { - hwndChild = Win32API.GetWindow(VisualizationWindow.Handle, Win32API.ShowWindowFlags.Show); - if (hwndChild != IntPtr.Zero) - { - Win32API.MoveWindow(hwndChild, 0, 0, VisualizationWindow.Width, VisualizationWindow.Height, true); - } + BassVis.BASSVIS_SetPlayState(_visParam, BASSVIS_PLAYSTATE.Play); + // Set the visualization window that was taken over from BASSVIS_ExecutePlugin BassVis.BASSVIS_SetVisPort(_visParam, _visParam.VisGenWinHandle, VisualizationWindow.Handle, @@ -319,18 +358,11 @@ VisualizationWindow.Width, VisualizationWindow.Height); - BassVis.BASSVIS_SetPlayState(_visParam, BASSVIS_PLAYSTATE.Play); + // Set CallBack for PlayState + _visCallback = BASSVIS_StateCallback; + BassVis.BASSVIS_WINAMPSetStateCallback(_visCallback); + BassVis.BASSVIS_SetOption(_visParam, BASSVIS_CONFIGFLAGS.BASSVIS_CONFIG_FFTAMP, 128); } - else - { - BassVis.BASSVIS_SetVisPort(_visParam, - _visParam.VisGenWinHandle, - IntPtr.Zero, - 0, - 0, - 0, - 0); - } // The Winamp Plugin has stolen focus on the MP window. Bring it back to froeground Win32API.SetForegroundWindow(GUIGraphicsContext.form.Handle); Index: Core/PlayList/PlayListPlayer.cs =================================================================== --- Core/PlayList/PlayListPlayer.cs (revision 28123) +++ Core/PlayList/PlayListPlayer.cs (working copy) @@ -135,6 +135,12 @@ get { return singletonPlayer; } } + // Returns current Playlist Position + public int CurrentPlaylistPos + { + get { return _currentItem; } + } + public void InitTest() { GUIGraphicsContext.Receivers += new SendMessageHandler(this.OnMessage);