1 #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 
9 /**
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
17  * is consuming, the reader will attempt multiple reads and only render the
18  * 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 
24 class NetPipeReaderView : public SampleView {
25 public:
NetPipeReaderView()26     NetPipeReaderView() {
27         fSocket = NULL;
28         fSync = true;
29     }
30 
~NetPipeReaderView()31     ~NetPipeReaderView() {
32         if (fSocket) {
33             delete fSocket;
34         }
35         fDataArray.reset();
36     }
requestMenu(SkOSMenu * menu)37     virtual void requestMenu(SkOSMenu* menu) {
38         menu->setTitle("Net Pipe Reader");
39         menu->appendTextField("Server IP", "Server IP", this->getSinkID(),
40                               "IP address");
41         menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync);
42     }
43 
44 protected:
readData(int cid,const void * data,size_t size,SkSocket::DataType type,void * context)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     }
50 
onRead(const void * data,size_t size)51     void onRead(const void* data, size_t size) {
52         if (size > 0)
53             fDataArray.append(size, (const char*)data);
54     }
55 
onQuery(SkEvent * evt)56     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 
onEvent(const SkEvent & evt)64     bool onEvent(const SkEvent& evt) {
65         SkString s;
66         if (SkOSMenu::FindText(evt, "Server IP", &s)) {
67             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         }
75         if (SkOSMenu::FindSwitchState(evt, "Sync", &fSync))
76             return true;
77         return this->INHERITED::onEvent(evt);
78     }
79 
onDrawContent(SkCanvas * canvas)80     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;
88                 while (fSocket->readPacket(readData, this) > 0 &&
89                        numreads < MAX_READS_PER_FRAME) {
90                     // 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);
93                     fDataArray.remove(0, dataToRemove);
94                     dataToRemove = fDataArray.count();
95                     ++numreads;
96                 }
97                 // clean up if max reads reached
98                 if (numreads == MAX_READS_PER_FRAME &&
99                     fDataArray.count() > dataToRemove)
100                     fDataArray.remove(0, dataToRemove);
101             }
102             else {
103                 if (fSocket->readPacket(readData, this) > 0)
104                     fDataArray.remove(0, dataToRemove);
105             }
106         }
107         else
108             fSocket->connectToServer();
109 
110         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 
119 private:
120     bool fSync;
121     SkTDArray<char> fDataArray;
122     SkTCPClient* fSocket;
123     typedef SampleView INHERITED;
124 };
125 
126 ///////////////////////////////////////////////////////////////////////////////
127 
MyFactory()128 static SkView* MyFactory() { return new NetPipeReaderView; }
129 static SkViewRegister reg(MyFactory);
130