]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Support on the fly audio mode change when CDA/FMV is playing.
authorToni Wilen <twilen@winuae.net>
Sun, 13 Aug 2017 12:25:17 +0000 (15:25 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 13 Aug 2017 12:25:17 +0000 (15:25 +0300)
audio.cpp
blkdev_cdimage.cpp
cd32_fmv.cpp
od-win32/blkdev_win32_ioctl.cpp
od-win32/cda_play.h

index 2f3a8b8fc2dd87fcd368980b9346a569b4314b9b..f950e5f792524eb119e4d47bc5547590fd3470fa 100644 (file)
--- a/audio.cpp
+++ b/audio.cpp
@@ -53,6 +53,7 @@
 #define PERIOD_MIN_NONCE 60
 
 int audio_channel_mask = 15;
+volatile bool cd_audio_mode_changed;
 
 STATIC_INLINE bool isaudio (void)
 {
@@ -1946,6 +1947,7 @@ void set_audio (void)
                events_schedule ();
        }
        set_config_changed ();
+       cd_audio_mode_changed = true;
 }
 
 void update_audio (void)
@@ -2492,6 +2494,11 @@ static bool audio_state_cda(int streamid)
 
 void audio_cda_new_buffer(uae_s16 *buffer, int length, int userdata, CDA_CALLBACK next_cd_audio_buffer_callback)
 {
+       if (length < 0 && cda_streamid > 0) {
+               audio_enable_stream(false, cda_streamid, 0, NULL);
+               cda_streamid = 0;
+               return;
+       }
        if (!buffer) {
                cda_bufptr = dummy_buffer;
                cda_length = 0;
index 8fd94f86f706dd94de0278248a3a91f67bfbd2cc..7f9848b597d6b3aee867be8fac6fb6a82fe7a929 100644 (file)
@@ -458,7 +458,7 @@ static void next_cd_audio_buffer_callback(int bufnum)
        uae_sem_post(&play_sem);
 }
 
-static void *cdda_play_func (void *v)
+static bool cdda_play_func2 (struct cdunit *cdu, int *outpos)
 {
        int cdda_pos;
        int bufnum;
@@ -466,9 +466,9 @@ static void *cdda_play_func (void *v)
        int idleframes = 0;
        int silentframes = 0;
        bool foundsub;
-       struct cdunit *cdu = (struct cdunit*)v;
        int oldtrack = -1;
        int mode = currprefs.sound_cdaudio;
+       bool restart = false;
 
        cdu->thread_active = true;
 
@@ -545,12 +545,14 @@ static void *cdda_play_func (void *v)
                        }
                        cdda_pos -= idleframes;
 
-                       _ftime (&tb2);
-                       diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
-                       diff -= cdu->cdda_delay;
-                       if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0)
-                               sleep_millis(-diff);
-                       setstate (cdu, AUDIO_STATUS_IN_PROGRESS, cdda_pos);
+                       if (*outpos < 0) {
+                               _ftime (&tb2);
+                               diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
+                               diff -= cdu->cdda_delay;
+                               if (idleframes >= 0 && diff < 0 && cdu->cdda_play > 0)
+                                       sleep_millis(-diff);
+                               setstate (cdu, AUDIO_STATUS_IN_PROGRESS, cdda_pos);
+                       }
 
                        sector = cdda_pos;
                        struct cdtoc *t1 = findtoc (cdu, &sector, false);
@@ -568,8 +570,13 @@ static void *cdda_play_func (void *v)
                }
 
                if (mode) {
-                       while (cda_bufon[bufnum] && cdu->cdda_play > 0)
+                       while (cda_bufon[bufnum] && cdu->cdda_play > 0) {
+                               if (cd_audio_mode_changed) {
+                                       restart = true;
+                                       goto end;
+                               }
                                sleep_millis(10);
+                       }
                } else {
                        cda->wait(bufnum);
                }
@@ -702,12 +709,20 @@ static void *cdda_play_func (void *v)
                                sleep_millis(10);
                }
 
+               if (cd_audio_mode_changed) {
+                       restart = true;
+                       goto end;
+               }
+
                bufnum = 1 - bufnum;
        }
 
 end:
+       *outpos = cdda_pos;
        if (mode) {
                next_cd_audio_buffer_callback(-1);
+               if (restart)
+                       audio_cda_new_buffer(NULL, -1, -1, NULL);
        } else {
                cda->wait (0);
                cda->wait (1);
@@ -718,13 +733,34 @@ end:
 
        delete cda;
 
-       cdu->cdda_play = 0;
-       write_log (_T("IMAGE CDDA: thread killed\n"));
+       write_log (_T("IMAGE CDDA: thread killed (%s)\n"), restart ? _T("restart") : _T("play end"));
+       cd_audio_mode_changed = false;
+       return restart;
+}
+
+static void *cdda_play_func (void *v)
+{
+       int outpos = -1;
+       struct cdunit *cdu = (struct cdunit*)v;
+       cd_audio_mode_changed = false;
+       for (;;) {
+               if (!cdda_play_func2(cdu, &outpos)) {
+                       cdu->cdda_play = 0;
+                       break;
+               }
+               cdu->cdda_start = outpos;
+               if (cdu->cdda_start + 150 >= cdu->cdda_end) {
+                       if (cdu->cdda_play >= 0)
+                               setstate (cdu, AUDIO_STATUS_PLAY_COMPLETE, cdu->cdda_end + 1);
+                       cdu->cdda_play = -1;
+                       break;
+               }
+               cdu->cdda_play = 1;
+       }
        cdu->thread_active = false;
        return NULL;
 }
 
-
 static void cdda_stop (struct cdunit *cdu)
 {
        if (cdu->cdda_play != 0) {
index 56d4b6087aa7220f69b3b8b6ada4b4cfac06d41c..0038bfde2f593d5002718684a9a3fb6f156dd0cc 100644 (file)
@@ -1404,6 +1404,17 @@ static void cd32_fmv_audio_handler(void)
        if (!fmv_ram_bank.baseaddr)
                return;
 
+       if (cd_audio_mode_changed) {
+               cd_audio_mode_changed = false;
+               if (cl450_play) {
+                       if (audio_mode) {
+                               audio_cda_new_buffer(NULL, -1, -1, NULL);
+                       }
+                       audio_mode = currprefs.sound_cdaudio;
+                       fmv_bufon[0] = fmv_bufon[1] = 0;
+               }
+       }
+
        if (cl450_buffer_offset == 0) {
                if (cl450_buffer_empty_cnt >= 2)
                        cl450_set_status(CL_INT_UND);
index 62f4e0289ab98a13911d0bc13b12293012f0224c..8abfab5de3bfd8684fa72030f2a36396332dfaea 100644 (file)
@@ -503,9 +503,8 @@ void ioctl_next_cd_audio_buffer_callback(int bufnum)
        uae_sem_post(&play_sem);
 }
 
-static void *cdda_play (void *v)
+static bool cdda_play2 (struct dev_info_ioctl *ciw, int *outpos)
 {
-       struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v;
        int cdda_pos;
        int bufnum;
        int buffered;
@@ -515,6 +514,7 @@ static void *cdda_play (void *v)
        int muteframes;
        int readblocksize = 2352 + 96;
        int mode = currprefs.sound_cdaudio;
+       bool restart = false;
 
        while (ciw->cdda_play == 0)
                sleep_millis(10);
@@ -589,20 +589,21 @@ static void *cdda_play (void *v)
                        }
                        cdda_pos -= idleframes;
 
-                       _ftime (&tb2);
-                       int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
-                       diff -= ciw->cdda_delay;
-                       if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0)
-                               sleep_millis(-diff);
-                       if (diff > 0 && !seensub) {
-                               int ch = diff / 7 + 25;
-                               if (ch > idleframes)
-                                       ch = idleframes;
-                               idleframes -= ch;
-                               cdda_pos += ch;
+                       if (*outpos < 0) {
+                               _ftime (&tb2);
+                               int diff = (tb2.time * (uae_s64)1000 + tb2.millitm) - (tb1.time * (uae_s64)1000 + tb1.millitm);
+                               diff -= ciw->cdda_delay;
+                               if (idleframes >= 0 && diff < 0 && ciw->cdda_play > 0)
+                                       sleep_millis(-diff);
+                               if (diff > 0 && !seensub) {
+                                       int ch = diff / 7 + 25;
+                                       if (ch > idleframes)
+                                               ch = idleframes;
+                                       idleframes -= ch;
+                                       cdda_pos += ch;
+                               }
+                               setstate (ciw, AUDIO_STATUS_IN_PROGRESS, cdda_pos);
                        }
-
-                       setstate (ciw, AUDIO_STATUS_IN_PROGRESS, cdda_pos);
                }
 
                if ((cdda_pos < ciw->cdda_end || ciw->cdda_end == 0xffffffff) && !ciw->cdda_paused && ciw->cdda_play) {
@@ -704,6 +705,11 @@ static void *cdda_play (void *v)
                while (ciw->cdda_paused && ciw->cdda_play == oldplay)
                        sleep_millis(10);
 
+               if (cd_audio_mode_changed) {
+                       restart = true;
+                       goto end;
+               }
+
                bufnum = 1 - bufnum;
 
        }
@@ -712,16 +718,40 @@ end:
 
        if (mode) {
                ioctl_next_cd_audio_buffer_callback(-1);
+               if (restart)
+                       audio_cda_new_buffer(NULL, -1, -1, NULL);
        } else {
                cda->wait (0);
                cda->wait (1);
        }
 
        ciw->subcodevalid = false;
+       cd_audio_mode_changed = false;
        delete cda;
 
-       ciw->cdda_play = 0;
        write_log (_T("IOCTL CDDA: thread killed\n"));
+       return restart;
+}
+
+static void *cdda_play (void *v)
+{
+       int outpos = -1;
+       struct dev_info_ioctl *ciw = (struct dev_info_ioctl*)v;
+       cd_audio_mode_changed = false;
+       for (;;) {
+               if (!cdda_play2(ciw, &outpos)) {
+                       break;
+               }
+               ciw->cdda_start = outpos;
+               if (ciw->cdda_start + 150 >= ciw->cdda_end) {
+                       if (ciw->cdda_play >= 0)
+                               setstate (ciw, AUDIO_STATUS_PLAY_COMPLETE, ciw->cdda_end + 1);
+                       ciw->cdda_play = -1;
+                       break;
+               }
+               ciw->cdda_play = 1;
+       }
+       ciw->cdda_play = 0;
        return NULL;
 }
 
index fe5e948c51adc371faae03cf9e34f40de0a6e4d7..2b8faea090b022a7dc8cdb99ec952edb7635af27 100644 (file)
@@ -3,6 +3,8 @@
 #include <dsound.h>
 #endif
 
+extern volatile bool cd_audio_mode_changed;
+
 class cda_audio
 {
 private: