2 * Copyright 2001-2014 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Marc Flerackers, mflerackers@androme.be
10 // Records a series of drawing instructions that can be "replayed" later.
21 #include <ByteOrder.h>
26 #include <AppServerLink.h>
28 #include <ObjectList.h>
29 #include <PicturePlayer.h>
30 #include <ServerProtocol.h>
32 #include "PicturePrivate.h"
35 static BObjectList
<BPicture
> sPictureList
;
36 static BLocker sPictureListLock
;
40 reconnect_pictures_to_app_server()
42 BAutolock
_(sPictureListLock
);
43 for (int32 i
= 0; i
< sPictureList
.CountItems(); i
++) {
44 BPicture::Private
picture(sPictureList
.ItemAt(i
));
45 picture
.ReconnectToAppServer();
50 BPicture::Private::Private(BPicture
* picture
)
58 BPicture::Private::ReconnectToAppServer()
64 struct _BPictureExtent_
{
65 _BPictureExtent_(const int32
& size
= 0);
68 const void* Data() const { return fNewData
; }
69 status_t
ImportData(const void* data
,
72 status_t
Flatten(BDataIO
* stream
);
73 status_t
Unflatten(BDataIO
* stream
);
75 int32
Size() const { return fNewSize
; }
76 status_t
SetSize(const int32
& size
);
78 bool AddPicture(BPicture
* picture
)
79 { return fPictures
.AddItem(picture
); }
80 void DeletePicture(const int32
& index
)
81 { delete static_cast<BPicture
*>
82 (fPictures
.RemoveItem(index
)); }
84 BList
* Pictures() { return &fPictures
; }
85 BPicture
* PictureAt(const int32
& index
)
86 { return static_cast<BPicture
*>
87 (fPictures
.ItemAt(index
)); }
89 int32
CountPictures() const
90 { return fPictures
.CountItems(); }
97 // In R5 this is a BArray<BPicture*>
98 // which is completely inline.
102 struct picture_header
{
103 int32 magic1
; // version ?
104 int32 magic2
; // endianess ?
118 BPicture::BPicture(const BPicture
& otherPicture
)
126 if (otherPicture
.fToken
!= -1) {
127 BPrivate::AppServerLink link
;
128 link
.StartMessage(AS_CLONE_PICTURE
);
129 link
.Attach
<int32
>(otherPicture
.fToken
);
131 status_t status
= B_ERROR
;
132 if (link
.FlushWithReply(status
) == B_OK
&& status
== B_OK
)
133 link
.Read
<int32
>(&fToken
);
139 if (otherPicture
.fExtent
->Size() > 0) {
140 fExtent
->ImportData(otherPicture
.fExtent
->Data(),
141 otherPicture
.fExtent
->Size());
143 for (int32 i
= 0; i
< otherPicture
.fExtent
->CountPictures(); i
++) {
145 = new BPicture(*otherPicture
.fExtent
->PictureAt(i
));
146 fExtent
->AddPicture(picture
);
152 BPicture::BPicture(BMessage
* data
)
161 if (data
->FindInt32("_ver", &version
) != B_OK
)
165 if (data
->FindInt8("_endian", &endian
) != B_OK
)
168 const void* pictureData
;
170 if (data
->FindData("_data", B_RAW_TYPE
, &pictureData
, (ssize_t
*)&size
)
176 BMessage pictureMessage
;
178 while (data
->FindMessage("piclib", i
++, &pictureMessage
) == B_OK
) {
179 BPicture
* picture
= new BPicture(&pictureMessage
);
180 fExtent
->AddPicture(picture
);
184 // TODO: For now. We'll see if it's worth to support old style data
185 debugger("old style BPicture data is not supported");
186 } else if (version
== 1) {
187 fExtent
->ImportData(data
, size
);
189 // swap_data(fExtent->fNewData, fExtent->fNewSize);
191 if (fExtent
->Size() > 0)
195 // Do we just free the data now?
196 if (fExtent
->Size() > 0)
199 // What with the sub pictures?
200 for (i
= fExtent
->CountPictures() - 1; i
>= 0; i
--)
201 fExtent
->DeletePicture(i
);
205 BPicture::BPicture(const void* data
, int32 size
)
208 // TODO: For now. We'll see if it's worth to support old style data
209 debugger("old style BPicture data is not supported");
214 BPicture::_InitData()
219 fExtent
= new (std::nothrow
) _BPictureExtent_
;
221 BAutolock
_(sPictureListLock
);
222 sPictureList
.AddItem(this);
226 BPicture::~BPicture()
228 BAutolock
_(sPictureListLock
);
229 sPictureList
.RemoveItem(this, false);
235 BPicture::_DisposeData()
238 BPrivate::AppServerLink link
;
240 link
.StartMessage(AS_DELETE_PICTURE
);
241 link
.Attach
<int32
>(fToken
);
252 BPicture::Instantiate(BMessage
* data
)
254 if (validate_instantiation(data
, "BPicture"))
255 return new BPicture(data
);
262 BPicture::Archive(BMessage
* data
, bool deep
) const
264 if (!const_cast<BPicture
*>(this)->_AssertLocalCopy())
267 status_t err
= BArchivable::Archive(data
, deep
);
271 err
= data
->AddInt32("_ver", 1);
275 err
= data
->AddInt8("_endian", B_HOST_IS_BENDIAN
);
279 err
= data
->AddData("_data", B_RAW_TYPE
, fExtent
->Data(), fExtent
->Size());
283 for (int32 i
= 0; i
< fExtent
->CountPictures(); i
++) {
284 BMessage pictureMessage
;
286 err
= fExtent
->PictureAt(i
)->Archive(&pictureMessage
, deep
);
290 err
= data
->AddMessage("piclib", &pictureMessage
);
300 BPicture::Perform(perform_code code
, void* arg
)
302 return BArchivable::Perform(code
, arg
);
307 BPicture::Play(void** callBackTable
, int32 tableEntries
, void* user
)
309 if (!_AssertLocalCopy())
312 BPrivate::PicturePlayer
player(fExtent
->Data(), fExtent
->Size(),
313 fExtent
->Pictures());
315 return player
.Play(callBackTable
, tableEntries
, user
);
320 BPicture::Flatten(BDataIO
* stream
)
322 // TODO: what about endianess?
324 if (!_AssertLocalCopy())
327 const picture_header header
= { 2, 0 };
328 ssize_t bytesWritten
= stream
->Write(&header
, sizeof(header
));
329 if (bytesWritten
< B_OK
)
332 if (bytesWritten
!= (ssize_t
)sizeof(header
))
335 return fExtent
->Flatten(stream
);
340 BPicture::Unflatten(BDataIO
* stream
)
342 // TODO: clear current picture data?
344 picture_header header
;
345 ssize_t bytesRead
= stream
->Read(&header
, sizeof(header
));
346 if (bytesRead
< B_OK
)
349 if (bytesRead
!= (ssize_t
)sizeof(header
)
350 || header
.magic1
!= 2 || header
.magic2
!= 0)
353 status_t status
= fExtent
->Unflatten(stream
);
357 // swap_data(fExtent->fNewData, fExtent->fNewSize);
359 if (!_AssertServerCopy())
362 // Data is now kept server side, remove the local copy
363 if (fExtent
->Data() != NULL
)
371 BPicture::_ImportOldData(const void* data
, int32 size
)
373 // TODO: We don't support old data for now
378 BPicture::SetToken(int32 token
)
385 BPicture::Token() const
392 BPicture::_AssertLocalCopy()
394 if (fExtent
->Data() != NULL
)
400 return _Download() == B_OK
;
405 BPicture::_AssertOldLocalCopy()
407 // TODO: We don't support old data for now
414 BPicture::_AssertServerCopy()
419 if (fExtent
->Data() == NULL
)
422 for (int32 i
= 0; i
< fExtent
->CountPictures(); i
++) {
423 if (!fExtent
->PictureAt(i
)->_AssertServerCopy())
427 return _Upload() == B_OK
;
434 if (fExtent
== NULL
|| fExtent
->Data() == NULL
)
437 BPrivate::AppServerLink link
;
439 link
.StartMessage(AS_CREATE_PICTURE
);
440 link
.Attach
<int32
>(fExtent
->CountPictures());
442 for (int32 i
= 0; i
< fExtent
->CountPictures(); i
++) {
443 BPicture
* picture
= fExtent
->PictureAt(i
);
445 link
.Attach
<int32
>(picture
->fToken
);
447 link
.Attach
<int32
>(-1);
449 link
.Attach
<int32
>(fExtent
->Size());
450 link
.Attach(fExtent
->Data(), fExtent
->Size());
452 status_t status
= B_ERROR
;
453 if (link
.FlushWithReply(status
) == B_OK
455 link
.Read
<int32
>(&fToken
);
463 BPicture::_Download()
465 ASSERT(fExtent
->Data() == NULL
);
466 ASSERT(fToken
!= -1);
468 BPrivate::AppServerLink link
;
470 link
.StartMessage(AS_DOWNLOAD_PICTURE
);
471 link
.Attach
<int32
>(fToken
);
473 status_t status
= B_ERROR
;
474 if (link
.FlushWithReply(status
) == B_OK
&& status
== B_OK
) {
476 link
.Read
<int32
>(&count
);
478 // Read sub picture tokens
479 for (int32 i
= 0; i
< count
; i
++) {
480 BPicture
* picture
= new BPicture
;
481 link
.Read
<int32
>(&picture
->fToken
);
482 fExtent
->AddPicture(picture
);
486 link
.Read
<int32
>(&size
);
487 status
= fExtent
->SetSize(size
);
489 link
.Read(const_cast<void*>(fExtent
->Data()), size
);
497 BPicture::Data() const
499 if (fExtent
->Data() == NULL
)
500 const_cast<BPicture
*>(this)->_AssertLocalCopy();
502 return fExtent
->Data();
507 BPicture::DataSize() const
509 if (fExtent
->Data() == NULL
)
510 const_cast<BPicture
*>(this)->_AssertLocalCopy();
512 return fExtent
->Size();
517 BPicture::Usurp(BPicture
* lameDuck
)
521 // Reinitializes the BPicture
532 BPicture
* lameDuck
= fUsurped
;
539 void BPicture::_ReservedPicture1() {}
540 void BPicture::_ReservedPicture2() {}
541 void BPicture::_ReservedPicture3() {}
545 BPicture::operator=(const BPicture
&)
552 _BPictureExtent_::_BPictureExtent_(const int32
& size
)
561 _BPictureExtent_::~_BPictureExtent_()
564 for (int32 i
= 0; i
< fPictures
.CountItems(); i
++)
565 delete static_cast<BPicture
*>(fPictures
.ItemAtFast(i
));
570 _BPictureExtent_::ImportData(const void* data
, const int32
& size
)
575 status_t status
= B_OK
;
577 status
= SetSize(size
);
580 memcpy(fNewData
, data
, size
);
587 _BPictureExtent_::Unflatten(BDataIO
* stream
)
593 ssize_t bytesRead
= stream
->Read(&count
, sizeof(count
));
594 if (bytesRead
< B_OK
)
596 if (bytesRead
!= (ssize_t
)sizeof(count
))
599 for (int32 i
= 0; i
< count
; i
++) {
600 BPicture
* picture
= new BPicture
;
601 status_t status
= picture
->Unflatten(stream
);
611 bytesRead
= stream
->Read(&size
, sizeof(size
));
612 if (bytesRead
< B_OK
)
615 if (bytesRead
!= (ssize_t
)sizeof(size
))
618 status_t status
= B_OK
;
620 status
= SetSize(size
);
625 bytesRead
= stream
->Read(fNewData
, size
);
626 if (bytesRead
< B_OK
)
629 if (bytesRead
!= (ssize_t
)size
)
637 _BPictureExtent_::Flatten(BDataIO
* stream
)
639 int32 count
= fPictures
.CountItems();
640 ssize_t bytesWritten
= stream
->Write(&count
, sizeof(count
));
641 if (bytesWritten
< B_OK
)
644 if (bytesWritten
!= (ssize_t
)sizeof(count
))
647 for (int32 i
= 0; i
< count
; i
++) {
648 status_t status
= PictureAt(i
)->Flatten(stream
);
653 bytesWritten
= stream
->Write(&fNewSize
, sizeof(fNewSize
));
654 if (bytesWritten
< B_OK
)
657 if (bytesWritten
!= (ssize_t
)sizeof(fNewSize
))
660 bytesWritten
= stream
->Write(fNewData
, fNewSize
);
661 if (bytesWritten
< B_OK
)
664 if (bytesWritten
!= fNewSize
)
672 _BPictureExtent_::SetSize(const int32
& size
)
677 if (size
== fNewSize
)
684 void* data
= realloc(fNewData
, size
);