blob: aef565359409f56c53f0a4c320d07d1562831a2f [file] [log] [blame]
yangsu@google.comf3493f02011-08-08 15:12:05 +00001#include "SampleCode.h"
2#include "SkView.h"
3#include "SkCanvas.h"
4#include "SkGradientShader.h"
5#include "SkGPipe.h"
6#include "SkSockets.h"
7#include "SkOSMenu.h"
8
yangsu@google.comef7bdfa2011-08-12 14:27:47 +00009/**
10 * A simple networked pipe reader
11 *
12 * This view will connect to a user specified server, in this case meaning any
13 * Skia app that's has a SkTCPServer set up to broadcast its piped drawing data,
14 * received all the data transmitted and attempt to reproduce the drawing calls.
15 * This reader will only keep the latest batch of data. In order to keep up with
16 * the server, which may be producing data at a much higher rate than the reader
rmistry@google.comd6176b02012-08-23 18:14:13 +000017 * is consuming, the reader will attempt multiple reads and only render the
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000018 * latest frame. this behavior can be adjusted by changing MAX_READS_PER_FRAME
19 * or disabled by setting fSync to false
20 */
21
22#define MAX_READS_PER_FRAME 12
23
yangsu@google.comf3493f02011-08-08 15:12:05 +000024class NetPipeReaderView : public SampleView {
25public:
rmistry@google.comd6176b02012-08-23 18:14:13 +000026 NetPipeReaderView() {
yangsu@google.comf3493f02011-08-08 15:12:05 +000027 fSocket = NULL;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000028 fSync = true;
yangsu@google.comf3493f02011-08-08 15:12:05 +000029 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000030
yangsu@google.comf3493f02011-08-08 15:12:05 +000031 ~NetPipeReaderView() {
32 if (fSocket) {
33 delete fSocket;
34 }
35 fDataArray.reset();
36 }
37 virtual void requestMenu(SkOSMenu* menu) {
38 menu->setTitle("Net Pipe Reader");
rmistry@google.comd6176b02012-08-23 18:14:13 +000039 menu->appendTextField("Server IP", "Server IP", this->getSinkID(),
yangsu@google.comf3493f02011-08-08 15:12:05 +000040 "IP address");
41 menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync);
42 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000043
yangsu@google.comf3493f02011-08-08 15:12:05 +000044protected:
45 static void readData(int cid, const void* data, size_t size,
46 SkSocket::DataType type, void* context) {
47 NetPipeReaderView* view = (NetPipeReaderView*)context;
48 view->onRead(data, size);
49 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000050
yangsu@google.comf3493f02011-08-08 15:12:05 +000051 void onRead(const void* data, size_t size) {
52 if (size > 0)
53 fDataArray.append(size, (const char*)data);
54 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000055
yangsu@google.comf3493f02011-08-08 15:12:05 +000056 bool onQuery(SkEvent* evt) {
57 if (SampleCode::TitleQ(*evt)) {
58 SampleCode::TitleR(evt, "Net Pipe Reader");
59 return true;
60 }
61 return this->INHERITED::onQuery(evt);
62 }
63
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000064 bool onEvent(const SkEvent& evt) {
yangsu@google.comf3493f02011-08-08 15:12:05 +000065 SkString s;
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000066 if (SkOSMenu::FindText(evt, "Server IP", &s)) {
yangsu@google.comf3493f02011-08-08 15:12:05 +000067 if (NULL != fSocket) {
68 delete fSocket;
69 }
70 fSocket = new SkTCPClient(s.c_str());
71 fSocket->connectToServer();
72 SkDebugf("Connecting to %s\n", s.c_str());
73 return true;
74 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000075 if (SkOSMenu::FindSwitchState(evt, "Sync", &fSync))
yangsu@google.comf3493f02011-08-08 15:12:05 +000076 return true;
77 return this->INHERITED::onEvent(evt);
78 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000079
yangsu@google.comf3493f02011-08-08 15:12:05 +000080 void onDrawContent(SkCanvas* canvas) {
81 if (NULL == fSocket)
82 return;
83
84 if (fSocket->isConnected()) {
85 int dataToRemove = fDataArray.count();
86 if (fSync) {
87 int numreads = 0;
rmistry@google.comd6176b02012-08-23 18:14:13 +000088 while (fSocket->readPacket(readData, this) > 0 &&
yangsu@google.comf3493f02011-08-08 15:12:05 +000089 numreads < MAX_READS_PER_FRAME) {
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000090 // at this point, new data has been read and stored, discard
91 // old data since it's not needed anymore
92 SkASSERT(fDataArray.count() > dataToRemove);
yangsu@google.comf3493f02011-08-08 15:12:05 +000093 fDataArray.remove(0, dataToRemove);
94 dataToRemove = fDataArray.count();
95 ++numreads;
96 }
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000097 // clean up if max reads reached
rmistry@google.comd6176b02012-08-23 18:14:13 +000098 if (numreads == MAX_READS_PER_FRAME &&
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000099 fDataArray.count() > dataToRemove)
100 fDataArray.remove(0, dataToRemove);
yangsu@google.comf3493f02011-08-08 15:12:05 +0000101 }
102 else {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000103 if (fSocket->readPacket(readData, this) > 0)
yangsu@google.comf3493f02011-08-08 15:12:05 +0000104 fDataArray.remove(0, dataToRemove);
105 }
106 }
107 else
108 fSocket->connectToServer();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000109
yangsu@google.comf3493f02011-08-08 15:12:05 +0000110 SkGPipeReader reader(canvas);
111 size_t bytesRead;
112 SkGPipeReader::Status fStatus = reader.playback(fDataArray.begin(),
113 fDataArray.count(),
114 &bytesRead);
115 SkASSERT(SkGPipeReader::kError_Status != fStatus);
116 this->inval(NULL);
117 }
118
119private:
120 bool fSync;
121 SkTDArray<char> fDataArray;
122 SkTCPClient* fSocket;
123 typedef SampleView INHERITED;
124};
125
yangsu@google.comf3493f02011-08-08 15:12:05 +0000126///////////////////////////////////////////////////////////////////////////////
127
128static SkView* MyFactory() { return new NetPipeReaderView; }
129static SkViewRegister reg(MyFactory);