diff options
Diffstat (limited to 'src/audio/player.c')
-rw-r--r-- | src/audio/player.c | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/src/audio/player.c b/src/audio/player.c index 35786284..20b40f73 100644 --- a/src/audio/player.c +++ b/src/audio/player.c | |||
@@ -33,11 +33,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
33 | #include <SDL_timer.h> | 33 | #include <SDL_timer.h> |
34 | 34 | ||
35 | #if defined (LAGRANGE_ENABLE_MPG123) | 35 | #if defined (LAGRANGE_ENABLE_MPG123) |
36 | # include <mpg123.h> | 36 | # include <mpg123.h> |
37 | #endif | ||
38 | #if defined (iPlatformAppleMobile) | ||
39 | # include "../ios.h" | ||
37 | #endif | 40 | #endif |
38 | 41 | ||
39 | /*----------------------------------------------------------------------------------------------*/ | 42 | /*----------------------------------------------------------------------------------------------*/ |
40 | 43 | ||
44 | iDeclareType(AVFAudioPlayer) /* iOS */ | ||
45 | |||
41 | iDeclareType(ContentSpec) | 46 | iDeclareType(ContentSpec) |
42 | 47 | ||
43 | enum iDecoderType { | 48 | enum iDecoderType { |
@@ -447,6 +452,7 @@ struct Impl_Player { | |||
447 | iInputBuf * data; | 452 | iInputBuf * data; |
448 | uint32_t lastInteraction; | 453 | uint32_t lastInteraction; |
449 | iDecoder * decoder; | 454 | iDecoder * decoder; |
455 | iAVFAudioPlayer * avfPlayer; /* iOS */ | ||
450 | }; | 456 | }; |
451 | 457 | ||
452 | iDefineTypeConstruction(Player) | 458 | iDefineTypeConstruction(Player) |
@@ -634,24 +640,40 @@ static void writeOutputSamples_Player_(void *plr, Uint8 *stream, int len) { | |||
634 | void init_Player(iPlayer *d) { | 640 | void init_Player(iPlayer *d) { |
635 | iZap(d->spec); | 641 | iZap(d->spec); |
636 | init_String(&d->mime); | 642 | init_String(&d->mime); |
637 | d->device = 0; | 643 | d->device = 0; |
638 | d->decoder = NULL; | 644 | d->decoder = NULL; |
639 | d->data = new_InputBuf(); | 645 | d->avfPlayer = NULL; |
640 | d->volume = 1.0f; | 646 | d->data = new_InputBuf(); |
641 | d->flags = 0; | 647 | d->volume = 1.0f; |
648 | d->flags = 0; | ||
642 | } | 649 | } |
643 | 650 | ||
644 | void deinit_Player(iPlayer *d) { | 651 | void deinit_Player(iPlayer *d) { |
645 | stop_Player(d); | 652 | stop_Player(d); |
646 | delete_InputBuf(d->data); | 653 | delete_InputBuf(d->data); |
647 | deinit_String(&d->mime); | 654 | deinit_String(&d->mime); |
655 | #if defined (iPlatformAppleMobile) | ||
656 | if (d->avfPlayer) { | ||
657 | delete_AVFAudioPlayer(d->avfPlayer); | ||
658 | } | ||
659 | #endif | ||
648 | } | 660 | } |
649 | 661 | ||
650 | iBool isStarted_Player(const iPlayer *d) { | 662 | iBool isStarted_Player(const iPlayer *d) { |
663 | #if defined (iPlatformAppleMobile) | ||
664 | if (d->avfPlayer) { | ||
665 | return isStarted_AVFAudioPlayer(d->avfPlayer); | ||
666 | } | ||
667 | #endif | ||
651 | return d->device != 0; | 668 | return d->device != 0; |
652 | } | 669 | } |
653 | 670 | ||
654 | iBool isPaused_Player(const iPlayer *d) { | 671 | iBool isPaused_Player(const iPlayer *d) { |
672 | #if defined (iPlatformAppleMobile) | ||
673 | if (d->avfPlayer) { | ||
674 | return isPaused_AVFAudioPlayer(d->avfPlayer); | ||
675 | } | ||
676 | #endif | ||
655 | if (!d->device) return iTrue; | 677 | if (!d->device) return iTrue; |
656 | return SDL_GetAudioDeviceStatus(d->device) == SDL_AUDIO_PAUSED; | 678 | return SDL_GetAudioDeviceStatus(d->device) == SDL_AUDIO_PAUSED; |
657 | } | 679 | } |
@@ -676,15 +698,26 @@ void updateSourceData_Player(iPlayer *d, const iString *mimeType, const iBlock * | |||
676 | case append_PlayerUpdate: { | 698 | case append_PlayerUpdate: { |
677 | const size_t oldSize = size_Block(&input->data); | 699 | const size_t oldSize = size_Block(&input->data); |
678 | const size_t newSize = size_Block(data); | 700 | const size_t newSize = size_Block(data); |
679 | iAssert(newSize >= oldSize); | 701 | if (input->isComplete) { |
702 | iAssert(newSize == oldSize); | ||
703 | break; | ||
704 | } | ||
680 | /* The old parts cannot have changed. */ | 705 | /* The old parts cannot have changed. */ |
681 | // iAssert(memcmp(constData_Block(&input->data), constData_Block(data), oldSize) == 0); | ||
682 | appendData_Block(&input->data, constBegin_Block(data) + oldSize, newSize - oldSize); | 706 | appendData_Block(&input->data, constBegin_Block(data) + oldSize, newSize - oldSize); |
683 | input->isComplete = iFalse; | ||
684 | break; | 707 | break; |
685 | } | 708 | } |
686 | case complete_PlayerUpdate: | 709 | case complete_PlayerUpdate: |
687 | input->isComplete = iTrue; | 710 | if (!input->isComplete) { |
711 | input->isComplete = iTrue; | ||
712 | #if defined (iPlatformAppleMobile) | ||
713 | iAssert(d->avfPlayer == NULL); | ||
714 | d->avfPlayer = new_AVFAudioPlayer(); | ||
715 | if (!setInput_AVFAudioPlayer(d->avfPlayer, &d->mime, &input->data)) { | ||
716 | delete_AVFAudioPlayer(d->avfPlayer); | ||
717 | d->avfPlayer = NULL; | ||
718 | } | ||
719 | #endif | ||
720 | } | ||
688 | break; | 721 | break; |
689 | } | 722 | } |
690 | signal_Condition(&input->changed); | 723 | signal_Condition(&input->changed); |
@@ -695,6 +728,13 @@ iBool start_Player(iPlayer *d) { | |||
695 | if (isStarted_Player(d)) { | 728 | if (isStarted_Player(d)) { |
696 | return iFalse; | 729 | return iFalse; |
697 | } | 730 | } |
731 | #if defined (iPlatformAppleMobile) | ||
732 | if (d->avfPlayer) { | ||
733 | play_AVFAudioPlayer(d->avfPlayer); | ||
734 | setNotIdle_Player(d); | ||
735 | return iTrue; | ||
736 | } | ||
737 | #endif | ||
698 | iContentSpec content = contentSpec_Player_(d); | 738 | iContentSpec content = contentSpec_Player_(d); |
699 | if (!content.output.freq) { | 739 | if (!content.output.freq) { |
700 | return iFalse; | 740 | return iFalse; |
@@ -713,6 +753,12 @@ iBool start_Player(iPlayer *d) { | |||
713 | } | 753 | } |
714 | 754 | ||
715 | void setPaused_Player(iPlayer *d, iBool isPaused) { | 755 | void setPaused_Player(iPlayer *d, iBool isPaused) { |
756 | #if defined (iPlatformAppleMobile) | ||
757 | if (d->avfPlayer) { | ||
758 | setPaused_AVFAudioPlayer(d->avfPlayer, isPaused); | ||
759 | return; | ||
760 | } | ||
761 | #endif | ||
716 | if (isStarted_Player(d)) { | 762 | if (isStarted_Player(d)) { |
717 | SDL_PauseAudioDevice(d->device, isPaused ? SDL_TRUE : SDL_FALSE); | 763 | SDL_PauseAudioDevice(d->device, isPaused ? SDL_TRUE : SDL_FALSE); |
718 | setNotIdle_Player(d); | 764 | setNotIdle_Player(d); |
@@ -720,6 +766,12 @@ void setPaused_Player(iPlayer *d, iBool isPaused) { | |||
720 | } | 766 | } |
721 | 767 | ||
722 | void stop_Player(iPlayer *d) { | 768 | void stop_Player(iPlayer *d) { |
769 | #if defined (iPlatformAppleMobile) | ||
770 | if (d->avfPlayer) { | ||
771 | stop_AVFAudioPlayer(d->avfPlayer); | ||
772 | return; | ||
773 | } | ||
774 | #endif | ||
723 | if (isStarted_Player(d)) { | 775 | if (isStarted_Player(d)) { |
724 | /* TODO: Stop the stream/decoder. */ | 776 | /* TODO: Stop the stream/decoder. */ |
725 | SDL_PauseAudioDevice(d->device, SDL_TRUE); | 777 | SDL_PauseAudioDevice(d->device, SDL_TRUE); |
@@ -735,6 +787,11 @@ void setVolume_Player(iPlayer *d, float volume) { | |||
735 | if (d->decoder) { | 787 | if (d->decoder) { |
736 | d->decoder->gain = d->volume; | 788 | d->decoder->gain = d->volume; |
737 | } | 789 | } |
790 | #if defined (iPlatformAppleMobile) | ||
791 | if (d->avfPlayer) { | ||
792 | setVolume_AVFAudioPlayer(d->avfPlayer, volume); | ||
793 | } | ||
794 | #endif | ||
738 | setNotIdle_Player(d); | 795 | setNotIdle_Player(d); |
739 | } | 796 | } |
740 | 797 | ||
@@ -762,11 +819,21 @@ const iString *tag_Player(const iPlayer *d, enum iPlayerTag tag) { | |||
762 | } | 819 | } |
763 | 820 | ||
764 | float time_Player(const iPlayer *d) { | 821 | float time_Player(const iPlayer *d) { |
822 | #if defined (iPlatformAppleMobile) | ||
823 | if (d->avfPlayer) { | ||
824 | return currentTime_AVFAudioPlayer(d->avfPlayer); | ||
825 | } | ||
826 | #endif | ||
765 | if (!d->decoder) return 0; | 827 | if (!d->decoder) return 0; |
766 | return (float) ((double) d->decoder->currentSample / (double) d->spec.freq); | 828 | return (float) ((double) d->decoder->currentSample / (double) d->spec.freq); |
767 | } | 829 | } |
768 | 830 | ||
769 | float duration_Player(const iPlayer *d) { | 831 | float duration_Player(const iPlayer *d) { |
832 | #if defined (iPlatformAppleMobile) | ||
833 | if (d->avfPlayer) { | ||
834 | return duration_AVFAudioPlayer(d->avfPlayer); | ||
835 | } | ||
836 | #endif | ||
770 | if (!d->decoder) return 0; | 837 | if (!d->decoder) return 0; |
771 | return (float) ((double) d->decoder->totalSamples / (double) d->spec.freq); | 838 | return (float) ((double) d->decoder->totalSamples / (double) d->spec.freq); |
772 | } | 839 | } |