summaryrefslogtreecommitdiff
path: root/src/audio
diff options
context:
space:
mode:
Diffstat (limited to 'src/audio')
-rw-r--r--src/audio/player.c87
-rw-r--r--src/audio/player.h30
2 files changed, 92 insertions, 25 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
44iDeclareType(AVFAudioPlayer) /* iOS */
45
41iDeclareType(ContentSpec) 46iDeclareType(ContentSpec)
42 47
43enum iDecoderType { 48enum 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
452iDefineTypeConstruction(Player) 458iDefineTypeConstruction(Player)
@@ -634,24 +640,40 @@ static void writeOutputSamples_Player_(void *plr, Uint8 *stream, int len) {
634void init_Player(iPlayer *d) { 640void 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
644void deinit_Player(iPlayer *d) { 651void 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
650iBool isStarted_Player(const iPlayer *d) { 662iBool 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
654iBool isPaused_Player(const iPlayer *d) { 671iBool 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
715void setPaused_Player(iPlayer *d, iBool isPaused) { 755void 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
722void stop_Player(iPlayer *d) { 768void 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
764float time_Player(const iPlayer *d) { 821float 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
769float duration_Player(const iPlayer *d) { 831float 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}
diff --git a/src/audio/player.h b/src/audio/player.h
index 82d95fd2..8753d811 100644
--- a/src/audio/player.h
+++ b/src/audio/player.h
@@ -49,21 +49,21 @@ enum iPlayerTag {
49void updateSourceData_Player (iPlayer *, const iString *mimeType, const iBlock *data, 49void updateSourceData_Player (iPlayer *, const iString *mimeType, const iBlock *data,
50 enum iPlayerUpdate update); 50 enum iPlayerUpdate update);
51 51
52iBool start_Player (iPlayer *); 52iBool start_Player (iPlayer *);
53void stop_Player (iPlayer *); 53void stop_Player (iPlayer *);
54void setPaused_Player (iPlayer *, iBool isPaused); 54void setPaused_Player (iPlayer *, iBool isPaused);
55void setVolume_Player (iPlayer *, float volume); 55void setVolume_Player (iPlayer *, float volume);
56void setFlags_Player (iPlayer *, int flags, iBool set); 56void setFlags_Player (iPlayer *, int flags, iBool set);
57void setNotIdle_Player (iPlayer *); 57void setNotIdle_Player (iPlayer *);
58 58
59int flags_Player (const iPlayer *); 59int flags_Player (const iPlayer *);
60const iString *tag_Player (const iPlayer *, enum iPlayerTag tag); 60const iString *tag_Player (const iPlayer *, enum iPlayerTag tag);
61iBool isStarted_Player (const iPlayer *); 61iBool isStarted_Player (const iPlayer *);
62iBool isPaused_Player (const iPlayer *); 62iBool isPaused_Player (const iPlayer *);
63float volume_Player (const iPlayer *); 63float volume_Player (const iPlayer *);
64float time_Player (const iPlayer *); 64float time_Player (const iPlayer *);
65float duration_Player (const iPlayer *); 65float duration_Player (const iPlayer *);
66float streamProgress_Player (const iPlayer *); /* normalized 0...1 */ 66float streamProgress_Player (const iPlayer *); /* normalized 0...1 */
67 67
68uint32_t idleTimeMs_Player (const iPlayer *); 68uint32_t idleTimeMs_Player (const iPlayer *);
69iString * metadataLabel_Player (const iPlayer *); 69iString * metadataLabel_Player (const iPlayer *);