Music Player Rework (2 Viewers)

Status
Not open for further replies.

elliottmc

Retired Team Member
  • Premium Supporter
  • August 7, 2005
    14,927
    6,061
    Cardiff, UK
    Home Country
    United Kingdom United Kingdom
    All of them are included and all of them should be set ready for testing.

    Only known issues are:
    - Too fast playback, when using WASAPI Shared Mode. Working on that
    - Possible crash, when WASAPI device is in use by other application - also working on that

    How separate are the fixes? Is it possible to have individual GIT branches for stuff without WASAPI so we can test and potentially merge that lot, and then have WASAPI merged later (hopefully still 1.4.0)?
     

    seco

    Retired Team Member
  • Premium Supporter
  • August 7, 2007
    1,575
    1,239
    Home Country
    Finland Finland
    @hwahrmann

    I started to investigate why Rockstar does not work with these changes.

    1) Bass.Net.dll version has changed so Rockstar fails to load this DLL, this is easy to fix

    2) I can only play one song in Rockstar. When playback is stopped, I cannot play any more songs until MP is restarted. I'm not sure why this is, this could have something to do with Bass.Net.dll changes but do you have any pointers where to look what has changed?

    I don't use Bass.NET stuff from MediaPortal, only direct calls to Bass.BASS* except when playback is started I do:

    Code:
    if (BassMusicPlayer.BassFreed)
      BassMusicPlayer.Player.InitBass();

    EDIT:

    Calling Bass.BASS_ChannelPlay(currentStream, false) second time gives me:

    BASS: Play() channelPlay() failed: BASS_ERROR_HANDLE

    This has worked fine before so something has changed in Bass.Net..

    If have three different kind of "currentStream":

    a) Bass.BASS_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT, streamproc, IntPtr.Zero); (Spotify)
    b) Bass.BASS_StreamCreateURL(strFile, 0, BASSFlag.BASS_DEFAULT, null, IntPtr.Zero); (Grooveshark)
    c) Bass.BASS_StreamCreateFile(strFile, 0, 0, BASSFlag.BASS_DEFAULT); (for Local MP3 in MP Music Database)

    Problem is that playback of c) works multiple times, a) and b) only works once. After playback of a) or b) none of a) b) or c) works..
     
    Last edited:

    hwahrmann

    Development Group
  • Team MediaPortal
  • September 15, 2004
    4,633
    2,457
    Vienna, Austria
    Home Country
    Austria Austria
    All of them are included and all of them should be set ready for testing.

    Only known issues are:
    - Too fast playback, when using WASAPI Shared Mode. Working on that
    - Possible crash, when WASAPI device is in use by other application - also working on that

    How separate are the fixes? Is it possible to have individual GIT branches for stuff without WASAPI so we can test and potentially merge that lot, and then have WASAPI merged later (hopefully still 1.4.0)?

    Nope. It is impossible to separate them.
    Either all or nothing.
     

    hwahrmann

    Development Group
  • Team MediaPortal
  • September 15, 2004
    4,633
    2,457
    Vienna, Austria
    Home Country
    Austria Austria
    @hwahrmann

    I started to investigate why Rockstar does not work with these changes.

    1) Bass.Net.dll version has changed so Rockstar fails to load this DLL, this is easy to fix

    2) I can only play one song in Rockstar. When playback is stopped, I cannot play any more songs until MP is restarted. I'm not sure why this is, this could have something to do with Bass.Net.dll changes but do you have any pointers where to look what has changed?

    I don't use Bass.NET stuff from MediaPortal, only direct calls to Bass.BASS* except when playback is started I do:

    Code:
    if (BassMusicPlayer.BassFreed)
      BassMusicPlayer.Player.InitBass();

    EDIT:

    Calling Bass.BASS_ChannelPlay(currentStream, false) second time gives me:

    BASS: Play() channelPlay() failed: BASS_ERROR_HANDLE

    This has worked fine before so something has changed in Bass.Net..

    If have three different kind of "currentStream":

    a) Bass.BASS_StreamCreate(44100, 2, BASSFlag.BASS_DEFAULT, streamproc, IntPtr.Zero); (Spotify)
    b) Bass.BASS_StreamCreateURL(strFile, 0, BASSFlag.BASS_DEFAULT, null, IntPtr.Zero); (Grooveshark)
    c) Bass.BASS_StreamCreateFile(strFile, 0, 0, BASSFlag.BASS_DEFAULT); (for Local MP3 in MP Music Database)

    Problem is that playback of c) works multiple times, a) and b) only works once. After playback of a) or b) none of a) b) or c) works..

    Interesting. There shouldn't be any changes which would cause problems like this. BASS_ERROR_HANDLE simply means that the handle is no longer valid. This could be because you have freed BASS itself or the handle.

    For use case b) and c) you could even use the MP Music Player framework. No need for you to handle that on your own. This would give you the ability to use WASAPI and ASIO.
    Don't know how your streamproc for spotify looks like, guess that is decoding some stuff.

    Is there any chance that i can debug this here?
     

    seco

    Retired Team Member
  • Premium Supporter
  • August 7, 2007
    1,575
    1,239
    Home Country
    Finland Finland
    Interesting. There shouldn't be any changes which would cause problems like this. BASS_ERROR_HANDLE simply means that the handle is no longer valid. This could be because you have freed BASS itself or the handle.

    For use case b) and c) you could even use the MP Music Player framework. No need for you to handle that on your own. This would give you the ability to use WASAPI and ASIO.
    Don't know how your streamproc for spotify looks like, guess that is decoding some stuff.

    Is there any chance that i can debug this here?

    Can you spot any obvious problem in this code?

    Code:
    namespace Rockstar.Mediaportal
    {
    	public abstract partial class BassPlayer : IPlayer
    	{
    		protected static Logger logger = LogManager.GetCurrentClassLogger();
     
    		private readonly SYNCPROC PlaybackEndProcDelegate;
     
    		private int currentStream;
     
    		private string filePath;
     
    		public override string CurrentFile
    		{
    			get { return filePath; }
    		}
     
    		public override bool Playing
    		{
    			get { return State == PlayerState.Playing || State == PlayerState.Paused; }
    		}
     
    		public override bool Stopped
    		{
    			get { return State == PlayerState.Stopped; }
    		}
     
    		public override bool Paused
    		{
    			get { return State == PlayerState.Paused; }
    		}
     
    		public override bool Initializing
    		{
    			get { return State == PlayerState.Stopped; }
    		}
     
    		public override bool SupportsReplay
    		{
    			// Do not support replay since we use two player instances
    			get { return false; }
    		}
     
    		public override int PlaybackType
    		{
    			// NORMAL = 0
    			get { return 0; }
    		}
     
    		public override bool IsRadio
    		{
    			// Do not act as a radio - otherwise TV Clients will go ballistic
    			get { return false; }
    		}
     
    		protected abstract int CreateBassStream(string strFile);
     
    		public override bool Play(string strFile)
    		{
    			filePath = strFile;
     
    			// We should initialize if MP has not initialized
    			if (BassMusicPlayer.BassFreed)
    				BassMusicPlayer.Player.InitBass();
     
    			currentStream = CreateBassStream(strFile);
     
    			if (Bass.BASS_ChannelPlay(currentStream, false))
    			{
    				RegisterPlaybackEndEvent(currentStream);
     
    				CurrentPlayingItem = CurrentItem;
    				State = PlayerState.Playing;
    			}
     
    			// Always return true no matter of result
    			return true;
    		}
     
    		public override void Stop()
    		{
    			if (State == PlayerState.Stopped)
    				return;
     
    			goNextTrack = false;
     
    			bool stopped = Bass.BASS_ChannelStop(currentStream);
     
    			Bass.BASS_StreamFree(currentStream);
     
    			if (stopped)
    			{
    				State = PlayerState.Stopped;
    				OnPlaybackStopped(CurrentTrack);
    			}
     
    			if (g_Player.Factory != playerFactory)
    			{
    				// Playback is not starting in Rockstar -> stop streaming
    				client.AbortStreaming();
    			}
    		}
     
    		public override void Pause()
    		{
    			if (State == PlayerState.Stopped)
    				return;
     
    			if (State == PlayerState.Paused)
    			{
    				State = PlayerState.Playing;
     
    				Bass.BASS_ChannelPlay(currentStream, false);
    			}
    			else
    			{
    				State = PlayerState.Paused;
     
    				Bass.BASS_ChannelPause(currentStream);
    			}
    		}
     
    		public override void Dispose()
    		{
    			// Do nothing
    		}
     
    		public override double CurrentPosition
    		{
    			get
    			{
    				if (currentStream == 0)
    				{
    					return 0;
    				}
     
    				return Bass.BASS_ChannelBytes2Seconds(currentStream,
    													  Bass.BASS_ChannelGetPosition(currentStream));
    			}
    		}
     
    		public override double Duration
    		{
    			get
    			{
    				if (CurrentPlayingItem != null)
    					return CurrentPlayingItem.Track.Length;				
     
    				return base.Duration;
    			}
    		}
     
    		private void PlaybackEndProc(int handle, int stream, int data, IntPtr userData)
    		{
    			Bass.BASS_ChannelRemoveSync(stream, handle);
     
    			OnPlaybackGoNext();
    		}
     
    		private int RegisterPlaybackEndEvent(int stream)
    		{
    			return Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END,
    											0, PlaybackEndProcDelegate, IntPtr.Zero);
    		}
    	}
    }

    CreateBassStream creates one of a), b) or c) and I think b) is something that should work out of the box
     
    Last edited:

    sleepycol

    Portal Pro
    June 2, 2006
    540
    39
    Home Country
    United Kingdom United Kingdom
    Hi hwahrmann,

    The detailed info is here:

    https://forum.team-mediaportal.com/...iewing-by-album-and-sorting-by-artist.115054/

    It would be great to get this issue solved as I really would like my music sorted as described above, I'm surprised no other users want this also.

    Cheers,
    Colin

    Hi hwahrmann,

    Did you get chance to include the above mod to the music sorting in your test build? If so, I will gladly test it for you.
    I know you have been busy with many other changes looking at the first post, so please don't be too annoyed at my question ;0)

    Thanks,
    Colin

    i am just looking at internal player capabilities in this build.
    I am not touching the GUI at all. i know that @jameson_uk was sometimes looking at it.
    It's a bit of a nightmare touching this part of code.
    I don't think that we should have sorting capailities in the GUI at all.
    The sorting should be done on the database query level, specified in the View.

    How do you mean no sorting capabilities in the GUI? Surely users want an option to be able to change the sorting order in the GUI?
    I think being able to specify a secondary sort in the MPconfig view setting would work. Wouldn't it be possible to add an option to sort by artist (as is possile at the moment) and then have a second sort column (secondary sort) users can specify another sort if they want. In this case sort by album name?

    Is this an easy change? I'm sure it would solve all sorting issues

    Cheers,
    Colin

    Hi Music Section developers,

    I have mentioned a few times about this issue and I believe it really impacts on the useability of the music player a lot, especially when browsing. It would be nice to know if it is being looked at and if not I will stop mentioning it. I think its a real shame about this sort order problem...

    Could it at least be added to a "to do" list so that the issue doesn't get lost?

    I know you guys do a great job and have lots to do and look at but I just wanted to ask if this will get looked into at some stage?

    Cheers,
    Colin
     
    Last edited:

    hwahrmann

    Development Group
  • Team MediaPortal
  • September 15, 2004
    4,633
    2,457
    Vienna, Austria
    Home Country
    Austria Austria
    Hi Colin,

    i fully understand your concerns, but this is the Rework of the Player and has nothing to do with how Songs are displayed n the GUI.
    It is totally unrelated.

    We might look at it in a later stage.

    thanks,

    Helmut
     

    hwahrmann

    Development Group
  • Team MediaPortal
  • September 15, 2004
    4,633
    2,457
    Vienna, Austria
    Home Country
    Austria Austria
    Interesting. There shouldn't be any changes which would cause problems like this. BASS_ERROR_HANDLE simply means that the handle is no longer valid. This could be because you have freed BASS itself or the handle.

    For use case b) and c) you could even use the MP Music Player framework. No need for you to handle that on your own. This would give you the ability to use WASAPI and ASIO.
    Don't know how your streamproc for spotify looks like, guess that is decoding some stuff.

    Is there any chance that i can debug this here?

    Can you spot any obvious problem in this code?

    Code:
    namespace Rockstar.Mediaportal
    {
    	public abstract partial class BassPlayer : IPlayer
    	{
    		protected static Logger logger = LogManager.GetCurrentClassLogger();
     
    		private readonly SYNCPROC PlaybackEndProcDelegate;
     
    		private int currentStream;
     
    		private string filePath;
     
    		public override string CurrentFile
    		{
    			get { return filePath; }
    		}
     
    		public override bool Playing
    		{
    			get { return State == PlayerState.Playing || State == PlayerState.Paused; }
    		}
     
    		public override bool Stopped
    		{
    			get { return State == PlayerState.Stopped; }
    		}
     
    		public override bool Paused
    		{
    			get { return State == PlayerState.Paused; }
    		}
     
    		public override bool Initializing
    		{
    			get { return State == PlayerState.Stopped; }
    		}
     
    		public override bool SupportsReplay
    		{
    			// Do not support replay since we use two player instances
    			get { return false; }
    		}
     
    		public override int PlaybackType
    		{
    			// NORMAL = 0
    			get { return 0; }
    		}
     
    		public override bool IsRadio
    		{
    			// Do not act as a radio - otherwise TV Clients will go ballistic
    			get { return false; }
    		}
     
    		protected abstract int CreateBassStream(string strFile);
     
    		public override bool Play(string strFile)
    		{
    			filePath = strFile;
     
    			// We should initialize if MP has not initialized
    			if (BassMusicPlayer.BassFreed)
    				BassMusicPlayer.Player.InitBass();
     
    			currentStream = CreateBassStream(strFile);
     
    			if (Bass.BASS_ChannelPlay(currentStream, false))
    			{
    				RegisterPlaybackEndEvent(currentStream);
     
    				CurrentPlayingItem = CurrentItem;
    				State = PlayerState.Playing;
    			}
     
    			// Always return true no matter of result
    			return true;
    		}
     
    		public override void Stop()
    		{
    			if (State == PlayerState.Stopped)
    				return;
     
    			goNextTrack = false;
     
    			bool stopped = Bass.BASS_ChannelStop(currentStream);
     
    			Bass.BASS_StreamFree(currentStream);
     
    			if (stopped)
    			{
    				State = PlayerState.Stopped;
    				OnPlaybackStopped(CurrentTrack);
    			}
     
    			if (g_Player.Factory != playerFactory)
    			{
    				// Playback is not starting in Rockstar -> stop streaming
    				client.AbortStreaming();
    			}
    		}
     
    		public override void Pause()
    		{
    			if (State == PlayerState.Stopped)
    				return;
     
    			if (State == PlayerState.Paused)
    			{
    				State = PlayerState.Playing;
     
    				Bass.BASS_ChannelPlay(currentStream, false);
    			}
    			else
    			{
    				State = PlayerState.Paused;
     
    				Bass.BASS_ChannelPause(currentStream);
    			}
    		}
     
    		public override void Dispose()
    		{
    			// Do nothing
    		}
     
    		public override double CurrentPosition
    		{
    			get
    			{
    				if (currentStream == 0)
    				{
    					return 0;
    				}
     
    				return Bass.BASS_ChannelBytes2Seconds(currentStream,
    													  Bass.BASS_ChannelGetPosition(currentStream));
    			}
    		}
     
    		public override double Duration
    		{
    			get
    			{
    				if (CurrentPlayingItem != null)
    					return CurrentPlayingItem.Track.Length;				
     
    				return base.Duration;
    			}
    		}
     
    		private void PlaybackEndProc(int handle, int stream, int data, IntPtr userData)
    		{
    			Bass.BASS_ChannelRemoveSync(stream, handle);
     
    			OnPlaybackGoNext();
    		}
     
    		private int RegisterPlaybackEndEvent(int stream)
    		{
    			return Bass.BASS_ChannelSetSync(stream, BASSSync.BASS_SYNC_END,
    											0, PlaybackEndProcDelegate, IntPtr.Zero);
    		}
    	}
    }

    CreateBassStream creates one of a), b) or c) and I think b) is something that should work out of the box

    The code looks absolutely ok. I can't see any problem.
    Only problem could be that for some reason the stream can't be created.

    I guess i would need a Spotify or Groveshark account to debug that. Right?
     

    seco

    Retired Team Member
  • Premium Supporter
  • August 7, 2007
    1,575
    1,239
    Home Country
    Finland Finland
    The code looks absolutely ok. I can't see any problem.
    Only problem could be that for some reason the stream can't be created.

    I guess i would need a Spotify or Groveshark account to debug that. Right?

    Not sure how I should debug this even by myself. The problem should not be specific to my plugin since all is just generic BASS stuff.

    Only thing I can suspect is that BassMusicPlayer.Player.InitBass() has changed so that it has some effect on this. But I should be able to test this by initializing the BASS directly in my plugin instead of InitBass() call. With this test there should be no MP BASS related code used in my plugin at all.
     

    seco

    Retired Team Member
  • Premium Supporter
  • August 7, 2007
    1,575
    1,239
    Home Country
    Finland Finland
    @hwahrmann

    1) I have pinpointed the code which is causing trouble with Rockstar

    BassAudioEngine.Initialize() calling Bass.BASS_Init(0, 48000, 0, IntPtr.Zero, Guid.Empty)
    BassAudioEngine.InitBass() calling Bass.BASS_Init(0, 48000, 0, IntPtr.Zero, Guid.Empty

    If either of these lines are executed, Rockstar is only able to play one song until MP is restarted. I'm not sure why this is but it would be nice to get this properly fixed.

    EDIT: More progress

    After first playback starts, Bass.BASS_GetDevice() returns "1" which is correct device and everything works fine. But when playback is stopped, GetDevice returns "0" which is the "no sound device" initialized by above and the second playback won't work.

    Then, if I use Bass.BASS_SetDevice(1) before playback, everything works fine. The problem with this is that this is an ugly hack and I don't actually know which device should be used (which device is actually the initialized one).

    I'm not sure why switch to "0 no sound device" is done and where. Also I'm not sure why this no sound device should be initialized at all in MediaPortal?

    2) Current BassAudioEngine code has few glitches
    - Bug: if (Config.SoundDevice == "Default Sound Device") should be "Default DirectSound Device" at least in my system
    - BassRegistration.BassRegistration.Register(); is called twice
    - _initialized = true; is called twice (not sure if this is a bug)
     
    Last edited:
    Status
    Not open for further replies.

    Users who are viewing this thread

    Top Bottom