protected override void SetMediaPosition(double pos)
        {
            Logger.LogTrace("DeezerRenderer::SetMediaPosition pos={0}", pos);

            if (FilterState != FilterState.Stopped)
            {
                if (_dzPlayer != IntPtr.Zero)
                {
                    dz_error_t err;

                    int resumePos = (int)pos;
                    if (resumePos != RenderPosition)
                    {
                        err = DeezerApi.dz_player_seek(_dzPlayer, null, IntPtr.Zero, (UInt64)(resumePos * 1e6));
                        DeezerApi.HandleDzErrorCode("dz_player_seek", err);
                    }

                    if (_evtPlayerPaused.WaitOne(DZ_OPERATION_TIMEOUT) == false)
                    {
                        DeezerApi.HandleDzErrorCode("[Event toggled by dz_player_seek]", dz_error_t.DZ_ERROR_PLAYER_SEEK_TIMEOUT);
                    }

                    Logger.LogTrace("[Event toggled by dz_player_seek] => DZ_PLAYER_EVENT_RENDER_TRACK_PAUSED");
                }
            }
        }
        //private void ResetAllEvents()
        //{
        //    _evtAppUserOfflineAvailable.Reset();
        //    _evtAppUserLoginOK.Reset();
        //    _evtPlayerPaused.Reset();
        //    _evtPlayerStreamReadyAfterSeek.Reset();
        //    _evtQueueListLoaded.Reset();
        //    _evtPlayerPlaybackStarted.Reset();
        //}

        protected override void DoStopRenderer()
        {
            StackTrace st = new StackTrace();

            Logger.LogTrace("DeezerRenderer::DoStopRenderer call Stack = {0}", st.ToString());

            if (FilterState != FilterState.Stopped)
            {
                if (_dzPlayer != IntPtr.Zero)
                {
                    dz_error_t err;

                    _evtPlayerPlaybackStopped.Reset();

                    err = DeezerApi.dz_player_stop(_dzPlayer, null, IntPtr.Zero);
                    DeezerApi.HandleDzErrorCode("dz_player_stop", err);

                    if (_evtPlayerPlaybackStopped.WaitOne(DZ_OPERATION_TIMEOUT) == false)
                    {
                        DeezerApi.HandleDzErrorCode("dz_player_pause", dz_error_t.DZ_ERROR_PLAYER_STOP_TIMEOUT);
                    }

                    RenderPosition = 0;

                    Logger.LogTrace("dz_player_stop => Success");
                }
            }
        }
        protected override void DoStartRendererWithHint(RenderingStartHint startHint)
        {
            dz_error_t err;

            _needNaturalNext = false;

            Logger.LogTrace("DeezerRenderer::DoStartRendererWithHint startHint={0}", startHint);

            if (renderMediaName == null || renderMediaName.Length <= 0)
            {
                return;
            }

            CheckIfInitialized();

            if (_dzConnect == IntPtr.Zero || _dzPlayer == IntPtr.Zero)
            {
                DeezerApi.HandleDzErrorCode("DeezerRenderer::DoStartRendererWithHint", dz_error_t.DZ_ERROR_CLASS_INSTANTIATION);
            }

            // --------------------------------------------------------------------
            _evtQueueListLoaded.Reset();
            err = DeezerApi.dz_player_load(_dzPlayer, null, IntPtr.Zero, renderMediaName);
            DeezerApi.HandleDzErrorCode("dz_player_load", err);

            if (_evtQueueListLoaded.WaitOne(DZ_OPERATION_TIMEOUT) == false)
            {
                DeezerApi.HandleDzErrorCode("dz_player_load", dz_error_t.DZ_ERROR_PLAYER_LOAD_TIMEOUT);
            }

            Logger.LogTrace("dz_player_load => Success");

            // --------------------------------------------------------------------

            // --------------------------------------------------------------------
            // Start playback using dz_player_play
            // This will trigger DZ_PLAYER_EVENT_RENDER_TRACK_START
            // Upon completion, _evtPlayerPlaybackStarted will be set.
            _evtPlayerPlaybackStarted.Reset();

            err = DeezerApi.dz_player_play(_dzPlayer, null, IntPtr.Zero,
                                           dz_player_play_command_t.DZ_PLAYER_PLAY_CMD_START_TRACKLIST,
                                           DeezerInterop.PlayerApi.Constants.DZ_INDEX_IN_QUEUELIST_CURRENT);

            DeezerApi.HandleDzErrorCode("dz_player_play", err);

            if (_evtPlayerPlaybackStarted.WaitOne(DZ_OPERATION_TIMEOUT) == false)
            {
                DeezerApi.HandleDzErrorCode("dz_player_play", dz_error_t.DZ_ERROR_PLAYER_PLAY_TIMEOUT);
            }

            Logger.LogTrace("dz_player_play => Success");
            // --------------------------------------------------------------------
        }
        protected override void SetAudioVolume(int vol)
        {
            if (_dzPlayer != IntPtr.Zero)
            {
                dz_error_t err;

                Logger.LogTrace("DeezerRenderer::SetAudioVolume vol={0}", vol);

                err = DeezerApi.dz_player_set_output_volume(_dzPlayer, null, IntPtr.Zero, vol);

                DeezerApi.HandleDzErrorCode("dz_player_set_output_volume", err);
            }
        }
        private void CleanupAppContext()
        {
            Logger.LogTrace("DeezerRenderer::CleanupAppContext => Cleaning up app context ...");

            dz_error_t err;

            if (_dzPlayer != IntPtr.Zero)
            {
                //_evtPlayerDeactivated.Reset();
                //_dzPlayerDeactivatedCB = new dz_activity_operation_callback(OnPlayerDeactivated);

                err = DeezerApi.dz_player_deactivate(_dzPlayer, _dzPlayerDeactivatedCB, IntPtr.Zero);

                DeezerApi.HandleDzErrorCode("dz_player_deactivate", err, false);

                //_evtPlayerDeactivated.WaitOne(DZ_OPERATION_TIMEOUT);
                Thread.Sleep(2000);

                Logger.LogTrace("dz_player_deactivate => Assuming Success");

                DeezerApi.dz_object_release(_dzPlayer);
                _dzPlayer = IntPtr.Zero;
            }

            if (_dzConnect != IntPtr.Zero)
            {
                //_evtConnectDeactivated.Reset();
                //_dzConnectDeactivatedCB = new dz_activity_operation_callback(OnConnectDeactivated);

                err = DeezerApi.dz_connect_deactivate(_dzConnect, _dzConnectDeactivatedCB, IntPtr.Zero);

                DeezerApi.HandleDzErrorCode("dz_connect_deactivate", err, false);

                //_evtConnectDeactivated.WaitOne(DZ_OPERATION_TIMEOUT);
                Thread.Sleep(2000);

                Logger.LogTrace("dz_connect_deactivate => Assuming Success");

                DeezerApi.dz_object_release(_dzConnect);
                _dzConnect = IntPtr.Zero;
            }
        }
        protected override void DoResumeRenderer(double fromPosition)
        {
            Logger.LogTrace("DeezerRenderer::DoResumeRenderer fromPosition={0}", fromPosition);

            dz_error_t err;

            if (_evtPlayerPaused.WaitOne(DZ_OPERATION_TIMEOUT) == false)
            {
                DeezerApi.HandleDzErrorCode("DeezerRenderer::DoResumeRenderer", dz_error_t.DZ_ERROR_PLAYER_PAUSE_NOT_STARTED);
            }

            Logger.LogTrace("DeezerRenderer::DoResumeRenderer player is now paused.");

            if (FilterState == FilterState.Paused)
            {
                if (_dzPlayer != IntPtr.Zero)
                {
                    int resumePos = (int)fromPosition;
                    if (resumePos != RenderPosition)
                    {
                        // dz_player_seek will trigger DZ_PLAYER_EVENT_MEDIASTREAM_DATA_READY_AFTER_SEEK
                        // Upon completion, _evtPlayerStreamReadyAfterSeek will be set.
                        _evtPlayerStreamReadyAfterSeek.Reset();
                        err = DeezerApi.dz_player_seek(_dzPlayer, null, IntPtr.Zero, (UInt64)(resumePos * 1e6));
                        DeezerApi.HandleDzErrorCode("dz_player_seek", err);

                        if (_evtPlayerStreamReadyAfterSeek.WaitOne(DZ_OPERATION_TIMEOUT) == false)
                        {
                            DeezerApi.HandleDzErrorCode("dz_player_seek", dz_error_t.DZ_ERROR_PLAYER_SEEK_TIMEOUT);
                        }

                        Logger.LogTrace("dz_player_seek => DZ_PLAYER_EVENT_MEDIASTREAM_DATA_READY_AFTER_SEEK");
                    }

                    err = DeezerApi.dz_player_resume(_dzPlayer, null, IntPtr.Zero);
                    DeezerApi.HandleDzErrorCode("dz_player_resume", err);
                }
            }
        }
        protected override void DoPauseRenderer()
        {
            Logger.LogTrace("DeezerRenderer::DoPauseRenderer");

            if (FilterState == FilterState.Running)
            {
                if (_dzPlayer != IntPtr.Zero)
                {
                    dz_error_t err;

                    _evtPlayerPaused.Reset();

                    err = DeezerApi.dz_player_pause(_dzPlayer, null, IntPtr.Zero);
                    DeezerApi.HandleDzErrorCode("dz_player_pause", err);

                    if (_evtPlayerPaused.WaitOne(DZ_OPERATION_TIMEOUT) == false)
                    {
                        DeezerApi.HandleDzErrorCode("dz_player_pause", dz_error_t.DZ_ERROR_PLAYER_PAUSE_TIMEOUT);
                    }

                    Logger.LogTrace("dz_player_pause => Success");
                }
            }
        }
        private void SetupAppContext()
        {
            if (_connected == false)
            {
                _evtAppUserOfflineAvailable.Reset();
                _evtAppUserLoginOK.Reset();

                Logger.LogTrace("DeezerRenderer::SetupConfig => Creating app context ...");

                dz_error_t err;

                _dzRenderProgressCB = new dz_player_onrenderprogress_cb(OnRenderProgress);
                _dzPlayerEventCB    = new dz_player_onevent_cb(OnPlayerEvent);
                _dzRendererEventCB  = new dz_player_onrendererevent_cb(OnRendererEvent);

                _dzConnect = DeezerApi.dz_connect_new(_dzConfig);
                if (_dzConnect == IntPtr.Zero)
                {
                    DeezerApi.HandleDzErrorCode("dz_connect_new", dz_error_t.DZ_ERROR_CLASS_INSTANTIATION);
                }

                //err = DeezerApi.dz_connect_debug_log_disable(_dzConnect);
                //DeezerApi.HandleDzErrorCode("dz_connect_debug_log_disable", err);

                err = DeezerApi.dz_connect_activate(_dzConnect, IntPtr.Zero);
                DeezerApi.HandleDzErrorCode("dz_connect_activate", err);

                err = DeezerApi.dz_connect_cache_path_set(_dzConnect, null, IntPtr.Zero, USER_CACHE_PATH);
                DeezerApi.HandleDzErrorCode("dz_connect_cache_path_set", err);

                _dzPlayer = DeezerApi.dz_player_new(_dzConnect);
                if (_dzPlayer == IntPtr.Zero)
                {
                    DeezerApi.HandleDzErrorCode("dz_player_new", dz_error_t.DZ_ERROR_CLASS_INSTANTIATION);
                }

                err = DeezerApi.dz_player_activate(_dzPlayer, IntPtr.Zero);
                DeezerApi.HandleDzErrorCode("dz_player_activate", err);

                err = DeezerApi.dz_player_set_event_cb(_dzPlayer, _dzPlayerEventCB);
                DeezerApi.HandleDzErrorCode("dz_player_set_event_cb", err);

                err = DeezerApi.dz_player_set_render_progress_cb(_dzPlayer, _dzRenderProgressCB, (UInt64)5e5);
                DeezerApi.HandleDzErrorCode("dz_player_set_render_progress_cb", err);

                err = DeezerApi.dz_player_set_renderer_event_cb(_dzPlayer, _dzRendererEventCB);
                DeezerApi.HandleDzErrorCode("dz_player_set_renderer_event_cb", err);

                string token = ProTONEConfig.DeezerUserAccessToken;
                err = DeezerApi.dz_connect_set_access_token(_dzConnect, null, IntPtr.Zero, token);
                DeezerApi.HandleDzErrorCode("dz_connect_set_access_token", err);

                err = DeezerApi.dz_connect_offline_mode(_dzConnect, null, IntPtr.Zero, false);
                DeezerApi.HandleDzErrorCode("dz_connect_offline_mode", err);

                if (_evtAppUserLoginOK.WaitOne(DZ_OPERATION_TIMEOUT) == false)
                {
                    DeezerApi.HandleDzErrorCode("DeezerRenderer::SetupConfig", dz_error_t.DZ_ERROR_CONNECT_SESSION_LOGIN_FAILED);
                }

                _connected = true;
            }
        }