summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-10-06 13:27:31 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-10-06 13:27:31 +0300
commit403d8fc06fda157b134f96328f98b9305509b5a3 (patch)
treea7ac4dc92dfcaa9fafddb65377a1d8a8cf61cccd
parent3ed9a627712bf6223e521e1f63a113404fea824a (diff)
Updating media content
Making it possible for media to be partially updated, for streaming. Also fixed a problem with multiple concurrent audio players started on a single media item.
m---------lib/the_Foundation0
-rw-r--r--src/audio/player.c10
-rw-r--r--src/media.c41
-rw-r--r--src/media.h7
-rw-r--r--src/ui/documentwidget.c8
5 files changed, 49 insertions, 17 deletions
diff --git a/lib/the_Foundation b/lib/the_Foundation
Subproject 4b041220b889a65e0dd5ec861e3c6982c968f0f Subproject ba3440ed5dc8e52d4b3d2da5121d9680ae213fa
diff --git a/src/audio/player.c b/src/audio/player.c
index f1d6a2c8..177613bb 100644
--- a/src/audio/player.c
+++ b/src/audio/player.c
@@ -477,10 +477,16 @@ void updateSourceData_Player(iPlayer *d, const iBlock *data, enum iPlayerUpdate
477 set_Block(&input->data, data); 477 set_Block(&input->data, data);
478 input->isComplete = iFalse; 478 input->isComplete = iFalse;
479 break; 479 break;
480 case append_PlayerUpdate: 480 case append_PlayerUpdate: {
481 append_Block(&input->data, data); 481 const size_t oldSize = size_Block(&input->data);
482 const size_t newSize = size_Block(data);
483 iAssert(newSize >= oldSize);
484 /* The old parts cannot have changed. */
485 iAssert(memcmp(constData_Block(&input->data), constData_Block(data), oldSize) == 0);
486 appendData_Block(&input->data, constBegin_Block(data) + oldSize, newSize - oldSize);
482 input->isComplete = iFalse; 487 input->isComplete = iFalse;
483 break; 488 break;
489 }
484 case complete_PlayerUpdate: 490 case complete_PlayerUpdate:
485 input->isComplete = iTrue; 491 input->isComplete = iTrue;
486 break; 492 break;
diff --git a/src/media.c b/src/media.c
index ad0682b1..b72ec32c 100644
--- a/src/media.c
+++ b/src/media.c
@@ -140,21 +140,41 @@ void clear_Media(iMedia *d) {
140} 140}
141 141
142void setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBlock *data, 142void setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBlock *data,
143 iBool allowHide) { 143 int flags) {
144 if (!mime || !data) { 144 const iBool isPartial = (flags & partialData_MediaFlag) != 0;
145 iMediaId existing = findLinkImage_Media(d, linkId); 145 const iBool allowHide = (flags & allowHide_MediaFlag) != 0;
146 if (existing) { 146 const iBool isDeleting = (!mime || !data);
147 iMediaId existing = findLinkImage_Media(d, linkId);
148 if (existing) {
149 if (isDeleting) {
147 iGmImage *img; 150 iGmImage *img;
148 take_PtrArray(&d->images, existing - 1, (void **) &img); 151 take_PtrArray(&d->images, existing - 1, (void **) &img);
149 delete_GmImage(img); 152 delete_GmImage(img);
150 } 153 }
151 else if ((existing = findLinkAudio_Media(d, linkId)) != 0) { 154 else {
152 iGmAudio *audio; 155 iAssert(isDeleting); /* images cannot be modified once set */
156 }
157 }
158 else if ((existing = findLinkAudio_Media(d, linkId)) != 0) {
159 iGmAudio *audio;
160 if (isDeleting) {
153 take_PtrArray(&d->audio, existing - 1, (void **) &audio); 161 take_PtrArray(&d->audio, existing - 1, (void **) &audio);
154 delete_GmAudio(audio); 162 delete_GmAudio(audio);
155 } 163 }
164 else {
165 audio = at_PtrArray(&d->audio, existing - 1);
166 iAssert(equal_String(&audio->props.mime, mime)); /* MIME cannot change */
167 updateSourceData_Player(audio->player, data, append_PlayerUpdate);
168 if (!isStarted_Player(audio->player)) {
169 /* Maybe the previous updates didn't have enough data. */
170 start_Player(audio->player);
171 }
172 if (!isPartial) {
173 updateSourceData_Player(audio->player, NULL, complete_PlayerUpdate);
174 }
175 }
156 } 176 }
157 else { 177 else if (!isDeleting) {
158 if (startsWith_String(mime, "image/")) { 178 if (startsWith_String(mime, "image/")) {
159 /* Copy the image to a texture. */ 179 /* Copy the image to a texture. */
160 /* TODO: Resize down to min(maximum texture size, window size). */ 180 /* TODO: Resize down to min(maximum texture size, window size). */
@@ -171,13 +191,14 @@ void setData_Media(iMedia *d, iGmLinkId linkId, const iString *mime, const iBloc
171 } 191 }
172 else if (startsWith_String(mime, "audio/")) { 192 else if (startsWith_String(mime, "audio/")) {
173 iGmAudio *audio = new_GmAudio(); 193 iGmAudio *audio = new_GmAudio();
174 audio->props.linkId = linkId; 194 audio->props.linkId = linkId; /* TODO: use a hash? */
175 audio->props.isPermanent = !allowHide; 195 audio->props.isPermanent = !allowHide;
176 set_String(&audio->props.mime, mime); 196 set_String(&audio->props.mime, mime);
177 /* TODO: What about update/complete, for streaming? */
178 updateSourceData_Player(audio->player, data, replace_PlayerUpdate); 197 updateSourceData_Player(audio->player, data, replace_PlayerUpdate);
198 if (!isPartial) {
199 updateSourceData_Player(audio->player, NULL, complete_PlayerUpdate);
200 }
179 pushBack_PtrArray(&d->audio, audio); 201 pushBack_PtrArray(&d->audio, audio);
180
181 /* TEST: Start playing right away. */ 202 /* TEST: Start playing right away. */
182 start_Player(audio->player); 203 start_Player(audio->player);
183 } 204 }
diff --git a/src/media.h b/src/media.h
index 6f460422..c19ad8ae 100644
--- a/src/media.h
+++ b/src/media.h
@@ -48,8 +48,13 @@ struct Impl_GmAudioInfo {
48iDeclareType(Media) 48iDeclareType(Media)
49iDeclareTypeConstruction(Media) 49iDeclareTypeConstruction(Media)
50 50
51enum iMediaFlags {
52 allowHide_MediaFlag = iBit(1),
53 partialData_MediaFlag = iBit(2),
54};
55
51void clear_Media (iMedia *); 56void clear_Media (iMedia *);
52void setData_Media (iMedia *, uint16_t linkId, const iString *mime, const iBlock *data, iBool allowHide); 57void setData_Media (iMedia *, uint16_t linkId, const iString *mime, const iBlock *data, int flags);
53 58
54iMediaId findLinkImage_Media (const iMedia *, uint16_t linkId); 59iMediaId findLinkImage_Media (const iMedia *, uint16_t linkId);
55iBool imageInfo_Media (const iMedia *, iMediaId imageId, iGmImageInfo *info_out); 60iBool imageInfo_Media (const iMedia *, iMediaId imageId, iGmImageInfo *info_out);
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index be9da513..165bf9cf 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -742,7 +742,7 @@ static void updateDocument_DocumentWidget_(iDocumentWidget *d, const iGmResponse
742 1, 742 1,
743 mimeStr, 743 mimeStr,
744 &response->body, 744 &response->body,
745 iFalse /* it's fixed */); 745 0);
746 redoLayout_GmDocument(d->doc); 746 redoLayout_GmDocument(d->doc);
747 } 747 }
748 else { 748 else {
@@ -1151,7 +1151,7 @@ static iBool handleMediaCommand_DocumentWidget_(iDocumentWidget *d, const char *
1151 req->linkId, 1151 req->linkId,
1152 meta_GmRequest(req->req), 1152 meta_GmRequest(req->req),
1153 body_GmRequest(req->req), 1153 body_GmRequest(req->req),
1154 iTrue); 1154 allowHide_MediaFlag);
1155 redoLayout_GmDocument(d->doc); 1155 redoLayout_GmDocument(d->doc);
1156 updateVisible_DocumentWidget_(d); 1156 updateVisible_DocumentWidget_(d);
1157 invalidate_DocumentWidget_(d); 1157 invalidate_DocumentWidget_(d);
@@ -1805,7 +1805,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1805 if (!requestMedia_DocumentWidget_(d, linkId)) { 1805 if (!requestMedia_DocumentWidget_(d, linkId)) {
1806 if (linkFlags & content_GmLinkFlag) { 1806 if (linkFlags & content_GmLinkFlag) {
1807 /* Dismiss shown content on click. */ 1807 /* Dismiss shown content on click. */
1808 setData_Media(media_GmDocument(d->doc), linkId, NULL, NULL, iTrue); 1808 setData_Media(media_GmDocument(d->doc), linkId, NULL, NULL, allowHide_MediaFlag);
1809 redoLayout_GmDocument(d->doc); 1809 redoLayout_GmDocument(d->doc);
1810 d->hoverLink = NULL; 1810 d->hoverLink = NULL;
1811 scroll_DocumentWidget_(d, 0); 1811 scroll_DocumentWidget_(d, 0);
@@ -1822,7 +1822,7 @@ static iBool processEvent_DocumentWidget_(iDocumentWidget *d, const SDL_Event *e
1822 linkId, 1822 linkId,
1823 meta_GmRequest(req->req), 1823 meta_GmRequest(req->req),
1824 body_GmRequest(req->req), 1824 body_GmRequest(req->req),
1825 iTrue); 1825 allowHide_MediaFlag);
1826 redoLayout_GmDocument(d->doc); 1826 redoLayout_GmDocument(d->doc);
1827 updateVisible_DocumentWidget_(d); 1827 updateVisible_DocumentWidget_(d);
1828 invalidate_DocumentWidget_(d); 1828 invalidate_DocumentWidget_(d);