Fix animation freeze when loading music files (#609)
* Implement async music loading * Simplify music filename parsing and fix "missing" on streams Co-authored-by: oldmud0 <oldmud0@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									d1fb7fde16
								
							
						
					
					
						commit
						5ce0e6416e
					
				@ -10,6 +10,8 @@
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <QFuture>
 | 
			
		||||
#include <QFutureWatcher>
 | 
			
		||||
 | 
			
		||||
class AOMusicPlayer {
 | 
			
		||||
public:
 | 
			
		||||
@ -24,8 +26,10 @@ public:
 | 
			
		||||
  int loop_start[4] = {0, 0, 0, 0};
 | 
			
		||||
  int loop_end[4] = {0, 0, 0, 0};
 | 
			
		||||
 | 
			
		||||
  QFutureWatcher<QString> music_watcher;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
  int play(QString p_song, int channel = 0, bool loop = false,
 | 
			
		||||
  QString play(QString p_song, int channel = 0, bool loop = false,
 | 
			
		||||
            int effect_flags = 0);
 | 
			
		||||
  void stop(int channel = 0);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,8 @@
 | 
			
		||||
#include <QTextCharFormat>
 | 
			
		||||
#include <QElapsedTimer>
 | 
			
		||||
 | 
			
		||||
#include <QFuture>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <stack>
 | 
			
		||||
 | 
			
		||||
@ -814,6 +816,8 @@ public slots:
 | 
			
		||||
                   bool steno);
 | 
			
		||||
  void on_reload_theme_clicked();
 | 
			
		||||
 | 
			
		||||
  void update_ui_music_name();
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
  void start_chat_ticking();
 | 
			
		||||
  void play_sfx();
 | 
			
		||||
 | 
			
		||||
@ -13,12 +13,13 @@ AOMusicPlayer::~AOMusicPlayer()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int AOMusicPlayer::play(QString p_song, int channel, bool loop,
 | 
			
		||||
QString AOMusicPlayer::play(QString p_song, int channel, bool loop,
 | 
			
		||||
                         int effect_flags)
 | 
			
		||||
{
 | 
			
		||||
  QFuture<QString> invoking_future = music_watcher.future();
 | 
			
		||||
  channel = channel % m_channelmax;
 | 
			
		||||
  if (channel < 0) // wtf?
 | 
			
		||||
    return BASS_ERROR_NOCHAN;
 | 
			
		||||
    return "[ERROR] Invalid Channel";
 | 
			
		||||
  QString f_path = ao_app->get_real_path(ao_app->get_music_path(p_song));
 | 
			
		||||
 | 
			
		||||
  unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE |
 | 
			
		||||
@ -43,6 +44,14 @@ int AOMusicPlayer::play(QString p_song, int channel, bool loop,
 | 
			
		||||
      newstream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, flags);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int error_code = BASS_ErrorGetCode();
 | 
			
		||||
 | 
			
		||||
  if (invoking_future.isCanceled() && channel == 0) {
 | 
			
		||||
      // Target future has changed. This stream has become irrelevant.
 | 
			
		||||
      // So even if the stream manages to finish after the latest one, we don't run
 | 
			
		||||
      // into order issues.
 | 
			
		||||
      return QString();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (ao_app->get_audio_output_device() != "default")
 | 
			
		||||
    BASS_ChannelSetDevice(m_stream_list[channel], BASS_GetDevice());
 | 
			
		||||
@ -109,7 +118,7 @@ int AOMusicPlayer::play(QString p_song, int channel, bool loop,
 | 
			
		||||
    BASS_ChannelStop(m_stream_list[channel]);
 | 
			
		||||
 | 
			
		||||
  m_stream_list[channel] = newstream;
 | 
			
		||||
  BASS_ChannelPlay(m_stream_list[channel], false);
 | 
			
		||||
  BASS_ChannelPlay(newstream, false);
 | 
			
		||||
  if (effect_flags & FADE_IN) {
 | 
			
		||||
    // Fade in our sample
 | 
			
		||||
    BASS_ChannelSetAttribute(newstream, BASS_ATTRIB_VOL, 0);
 | 
			
		||||
@ -120,12 +129,32 @@ int AOMusicPlayer::play(QString p_song, int channel, bool loop,
 | 
			
		||||
  else
 | 
			
		||||
    this->set_volume(m_volume[channel], channel);
 | 
			
		||||
 | 
			
		||||
  BASS_ChannelSetSync(m_stream_list[channel], BASS_SYNC_DEV_FAIL, 0,
 | 
			
		||||
  BASS_ChannelSetSync(newstream, BASS_SYNC_DEV_FAIL, 0,
 | 
			
		||||
                      ao_app->BASSreset, 0);
 | 
			
		||||
 | 
			
		||||
  this->set_looping(loop, channel); // Have to do this here due to any
 | 
			
		||||
                                    // crossfading-related changes, etc.
 | 
			
		||||
  return BASS_ErrorGetCode();
 | 
			
		||||
 | 
			
		||||
  bool is_stop = (p_song == "~stop.mp3");
 | 
			
		||||
  QString p_song_clear = QUrl(p_song).fileName();
 | 
			
		||||
  p_song_clear = p_song_clear.left(p_song_clear.lastIndexOf('.'));
 | 
			
		||||
 | 
			
		||||
  if (is_stop) {
 | 
			
		||||
    return QObject::tr("None");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (error_code == BASS_ERROR_HANDLE) { // Cheap hack to see if file missing
 | 
			
		||||
    return QObject::tr("[MISSING] %1").arg(p_song_clear);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (p_song.startsWith("http") && channel == 0) {
 | 
			
		||||
    return QObject::tr("[STREAM] %1").arg(p_song_clear);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (channel == 0)
 | 
			
		||||
    return p_song_clear;
 | 
			
		||||
 | 
			
		||||
  return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AOMusicPlayer::stop(int channel)
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,8 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
			
		||||
 | 
			
		||||
  music_player = new AOMusicPlayer(this, ao_app);
 | 
			
		||||
  music_player->set_volume(0);
 | 
			
		||||
  connect(&music_player->music_watcher, &QFutureWatcher<QString>::finished,
 | 
			
		||||
          this, &Courtroom::update_ui_music_name, Qt::QueuedConnection);
 | 
			
		||||
 | 
			
		||||
  sfx_player = new AOSfxPlayer(this, ao_app);
 | 
			
		||||
  sfx_player->set_volume(0);
 | 
			
		||||
@ -3807,13 +3809,8 @@ void Courtroom::handle_song(QStringList *p_contents)
 | 
			
		||||
  int effect_flags = 0; // No effects by default - vanilla functionality
 | 
			
		||||
 | 
			
		||||
  QString f_song = f_contents.at(0);
 | 
			
		||||
  QString f_song_clear = f_song.left(f_song.lastIndexOf("."));
 | 
			
		||||
  if (f_song.startsWith("http")) {
 | 
			
		||||
    QByteArray f_song_bytearray = f_song.toUtf8();
 | 
			
		||||
    QString f_song_decoded = QUrl::fromPercentEncoding(f_song_bytearray);
 | 
			
		||||
    f_song_clear = f_song_decoded.left(f_song_decoded.lastIndexOf("."));
 | 
			
		||||
  }
 | 
			
		||||
  f_song_clear = f_song_clear.right(f_song_clear.length() - (f_song_clear.lastIndexOf("/") + 1));
 | 
			
		||||
  QString f_song_clear = QUrl(f_song).fileName();
 | 
			
		||||
  f_song_clear = f_song_clear.left(f_song_clear.lastIndexOf('.'));
 | 
			
		||||
 | 
			
		||||
  int n_char = f_contents.at(1).toInt(&ok);
 | 
			
		||||
  if (!ok)
 | 
			
		||||
@ -3862,27 +3859,25 @@ void Courtroom::handle_song(QStringList *p_contents)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int error_code = music_player->play(f_song, channel, looping, effect_flags);
 | 
			
		||||
 | 
			
		||||
  if (is_stop) {
 | 
			
		||||
    ui_music_name->setText(tr("None"));
 | 
			
		||||
    return;
 | 
			
		||||
  QFuture<QString> future = QtConcurrent::run(music_player, &AOMusicPlayer::play, f_song, channel,
 | 
			
		||||
                                              looping, effect_flags);
 | 
			
		||||
  if (channel == 0) {
 | 
			
		||||
    // Current song UI only displays the song playing, not other channels.
 | 
			
		||||
    // Any other music playing is irrelevant.
 | 
			
		||||
    if (music_player->music_watcher.isRunning()) {
 | 
			
		||||
        music_player->music_watcher.cancel();
 | 
			
		||||
    }
 | 
			
		||||
    music_player->music_watcher.setFuture(future);
 | 
			
		||||
    ui_music_name->setText(tr("[LOADING] %1").arg(f_song_clear));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  if (error_code == BASS_ERROR_HANDLE) { // Cheap hack to see if file missing
 | 
			
		||||
    ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (f_song.startsWith("http") && channel == 0) {
 | 
			
		||||
    ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (channel == 0){
 | 
			
		||||
    ui_music_name->setText(f_song_clear);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
void Courtroom::update_ui_music_name()
 | 
			
		||||
{
 | 
			
		||||
    QString result = music_player->music_watcher.result();
 | 
			
		||||
    if (result.isEmpty())
 | 
			
		||||
      return;
 | 
			
		||||
    ui_music_name->setText(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Courtroom::handle_wtce(QString p_wtce, int variant)
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user