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: 26 NetPipeReaderView() { 27 fSocket = NULL; 28 fSync = true; 29 } 30 31 ~NetPipeReaderView() { 32 if (fSocket) { 33 delete fSocket; 34 } 35 fDataArray.reset(); 36 } 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: 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 51 void onRead(const void* data, size_t size) { 52 if (size > 0) 53 fDataArray.append(size, (const char*)data); 54 } 55 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 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 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 128 static SkView* MyFactory() { return new NetPipeReaderView; } 129 static SkViewRegister reg(MyFactory); 130