SimpleAudioPlayer CurrentPosition и Duration всегда равны 0 - PullRequest
0 голосов
/ 04 ноября 2019

Я пытаюсь создать плейлист в Xamarin Forms, используя список аудио, которые можно добавить в ListView через другие ListView с. Я использую плагин SimpleAudioPlayer , чтобы достичь этого. Я хотел бы, чтобы несколько аудио воспроизводились последовательно.

Функция воспроизведения работает нормально, а Stream не выбрасывает Exception. Прямо сейчас код воспроизводит всегда один и тот же звук несколько раз. Чтобы достичь последовательного эффекта, я попытался создать цикл while, используя свойства CurrentPosition и Duration внутри цикла for для каждой дорожки в списке воспроизведения, но я не нашел никакой самообвиняемой документации об этих двух свойствах.

using G.Models;
using Plugin.SimpleAudioPlayer;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Input;
using Xamarin.Forms;

namespace G.ViewModels
{
    class ABSViewModel : BaseViewModel{
        public ObservableCollection<PlayListItem> Playlist { get; set; }
        public ICommand PlayPlaylistCommand { get; set; }
        private PlayListItem playlistSelectedItem;
        public PlayListItem PlaylistSelectedItem
        { 
            get {
                return playlistSelectedItem;
            }
            set {
                playlistSelectedItem = value;
            }
        }

        public ABSViewModel()
        {
            audio = CrossSimpleAudioPlayer.CreateSimpleAudioPlayer();
            PlayButtonText = "PLAY";
            PlayButtonImage = "play_icon.png";
            PlayButtonFlag = "1";
            PlayPlaylistCommand = new Command(PlayPlaylist);
            Playlist = new ObservableCollection<PlayListItem>();
        }

        private async void PlayPlaylist()
        {
            if (PlayButtonFlag == "1")
            {
                PlayButtonText = "PAUSE";
                PlayButtonImage = "pause_icon.png";
                PlayButtonFlag = "0";
                int startPosition;

                if(PlaylistSelectedItem != null)
                {
                    startPosition = 0;
                }
                else
                {
                    startPosition = Playlist.IndexOf(playlistSelectedItem);
                }
                for(int i = 0; i < Playlist.Count; i++)
                {
                    if (audio.IsPlaying) audio.Stop();
                    PlaylistSelectedItem = Playlist[i];
                    OnPropertyChanged(nameof(Playlist));
                    audio.Load(GetStreamFromFile(Playlist[i].Name + ".wav"));
                    audio.Play();
                    while (audio.CurrentPosition != audio.Duration) {
                        Debug.WriteLine("Test");
                    }
                }
            }
            else
            {
                PlayButtonText = "PLAY";
                PlayButtonImage = "play_icon.png";
                PlayButtonFlag = "1";
                if (audio.IsPlaying) audio.Pause();
            }
            NotifyButtonChange();
        }


        Stream GetStreamFromFile(string filename)
        {
            var assembly = typeof(App).GetTypeInfo().Assembly;
            var stream = assembly.GetManifestResourceStream("G2019." + "RSNZBile.wav");
            return stream;
        }

        private void NotifyButtonChange()
        {
            OnPropertyChanged(nameof(PlayButtonText));
            OnPropertyChanged(nameof(PlayButtonImage));
            OnPropertyChanged(nameof(PlayButtonFlag));
        }

    }
}

Я опускаю Command s, чтобы добавить элементы в список воспроизведения или остановить воспроизведение списка воспроизведения, потому что я думаю, что они находятся вне контекста. Теперь, когда я нажимаю кнопку «Воспроизвести», я вижу в отладчике, что мой цикл while вообще не запустился. Таким образом, проигрыватель воспроизводит все элементы списка воспроизведения за несколько миллисекунд, и единственный, который человек может услышать, является последним. Это потому, что мои свойства CurrentPosition и Duration установлены на 0. Почему? Кто-нибудь пытался сделать что-то подобное?

1 Ответ

0 голосов
/ 06 ноября 2019

Если кому-то интересно, я решил проблему с помощью события PlaybackEnded. Каждый фрагмент кода, который был внутри цикла for, был перемещен в функцию-обработчик PlaybackEnded без необходимости while. Значение Duration, установленное на 0, все еще остается загадкой.

private async void PlayPlaylist(string value)
{
    if (PlayButtonMode == 1)
    {
        int startPosition;
        //Playing playlist from selected item if user selected one. (first item if he didn't)
        if (PlaylistSelectedItem == null) startPosition = 0;
        else startPosition = Playlist.IndexOf(playlistSelectedItem);
        if (audio.IsPlaying) audio.Stop();
        PlaylistSelectedItem = Playlist[startPosition];
        audio.Load(GetStreamFromFile(PlaylistSelectedItem.Name + ".wav"));
        audio.Play();
        audio.PlaybackEnded += Audio_PlaybackEnded;
    }
    else if (PlayButtonMode == 2)
        audio.Play();
    else
    {
        if (audio.IsPlaying) audio.Pause();
    }
    ChangeButtonMode(PlayButtonMode);
}

private void ChangeButtonMode(int senderMode)
{
    if (senderMode == 1 || senderMode == 2)
    {
        PlayButtonText = "PAUSE";
        PlayButtonImage = "pause_icon.png";
        PlayButtonMode = 0;
    }
    else
    {
        PlayButtonText = "PLAY";
        PlayButtonImage = "play_icon.png";
        if (senderMode == 3) PlayButtonMode = 1; 
        else PlayButtonMode = 2;
    }
    NotifyButtonChange();
}

private void Audio_PlaybackEnded(object sender, EventArgs e)
{
    //Check if next playlist element exists
    if(Playlist.IndexOf(PlaylistSelectedItem) + 1 < Playlist.Count)
    {
        PlaylistSelectedItem = Playlist[Playlist.IndexOf(PlaylistSelectedItem) + 1];
        if (audio.IsPlaying) audio.Stop();
        audio.Load(GetStreamFromFile(PlaylistSelectedItem.Name + ".wav"));
        audio.Play();
        audio.PlaybackEnded += Audio_PlaybackEnded;
    }else if(audio.IsPlaying) audio.Stop();   
}


private void StopAudio()
{
    if (audio.IsPlaying)
        audio.Stop();
    ChangeButtonMode(3);
}
...