|  | #include "SampleCode.h" | 
|  | #include "SkView.h" | 
|  | #include "SkCanvas.h" | 
|  | #include "SkGradientShader.h" | 
|  | #include "SkGPipe.h" | 
|  | #include "SkSockets.h" | 
|  | #include "SkOSMenu.h" | 
|  |  | 
|  | /** | 
|  | * A simple networked pipe reader | 
|  | * | 
|  | * This view will connect to a user specified server, in this case meaning any | 
|  | * Skia app that's has a SkTCPServer set up to broadcast its piped drawing data, | 
|  | * received all the data transmitted and attempt to reproduce the drawing calls. | 
|  | * This reader will only keep the latest batch of data. In order to keep up with | 
|  | * the server, which may be producing data at a much higher rate than the reader | 
|  | * is consuming, the reader will attempt multiple reads and only render the | 
|  | * latest frame. this behavior can be adjusted by changing MAX_READS_PER_FRAME | 
|  | * or disabled by setting fSync to false | 
|  | */ | 
|  |  | 
|  | #define MAX_READS_PER_FRAME 12 | 
|  |  | 
|  | class NetPipeReaderView : public SampleView { | 
|  | public: | 
|  | NetPipeReaderView() { | 
|  | fSocket = NULL; | 
|  | fSync = true; | 
|  | } | 
|  |  | 
|  | ~NetPipeReaderView() { | 
|  | if (fSocket) { | 
|  | delete fSocket; | 
|  | } | 
|  | fDataArray.reset(); | 
|  | } | 
|  | virtual void requestMenu(SkOSMenu* menu) { | 
|  | menu->setTitle("Net Pipe Reader"); | 
|  | menu->appendTextField("Server IP", "Server IP", this->getSinkID(), | 
|  | "IP address"); | 
|  | menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | static void readData(int cid, const void* data, size_t size, | 
|  | SkSocket::DataType type, void* context) { | 
|  | NetPipeReaderView* view = (NetPipeReaderView*)context; | 
|  | view->onRead(data, size); | 
|  | } | 
|  |  | 
|  | void onRead(const void* data, size_t size) { | 
|  | if (size > 0) | 
|  | fDataArray.append(size, (const char*)data); | 
|  | } | 
|  |  | 
|  | bool onQuery(SkEvent* evt) { | 
|  | if (SampleCode::TitleQ(*evt)) { | 
|  | SampleCode::TitleR(evt, "Net Pipe Reader"); | 
|  | return true; | 
|  | } | 
|  | return this->INHERITED::onQuery(evt); | 
|  | } | 
|  |  | 
|  | bool onEvent(const SkEvent& evt) { | 
|  | SkString s; | 
|  | if (SkOSMenu::FindText(evt, "Server IP", &s)) { | 
|  | if (NULL != fSocket) { | 
|  | delete fSocket; | 
|  | } | 
|  | fSocket = new SkTCPClient(s.c_str()); | 
|  | fSocket->connectToServer(); | 
|  | SkDebugf("Connecting to %s\n", s.c_str()); | 
|  | return true; | 
|  | } | 
|  | if (SkOSMenu::FindSwitchState(evt, "Sync", &fSync)) | 
|  | return true; | 
|  | return this->INHERITED::onEvent(evt); | 
|  | } | 
|  |  | 
|  | void onDrawContent(SkCanvas* canvas) { | 
|  | if (NULL == fSocket) | 
|  | return; | 
|  |  | 
|  | if (fSocket->isConnected()) { | 
|  | int dataToRemove = fDataArray.count(); | 
|  | if (fSync) { | 
|  | int numreads = 0; | 
|  | while (fSocket->readPacket(readData, this) > 0 && | 
|  | numreads < MAX_READS_PER_FRAME) { | 
|  | // at this point, new data has been read and stored, discard | 
|  | // old data since it's not needed anymore | 
|  | SkASSERT(fDataArray.count() > dataToRemove); | 
|  | fDataArray.remove(0, dataToRemove); | 
|  | dataToRemove = fDataArray.count(); | 
|  | ++numreads; | 
|  | } | 
|  | // clean up if max reads reached | 
|  | if (numreads == MAX_READS_PER_FRAME && | 
|  | fDataArray.count() > dataToRemove) | 
|  | fDataArray.remove(0, dataToRemove); | 
|  | } | 
|  | else { | 
|  | if (fSocket->readPacket(readData, this) > 0) | 
|  | fDataArray.remove(0, dataToRemove); | 
|  | } | 
|  | } | 
|  | else | 
|  | fSocket->connectToServer(); | 
|  |  | 
|  | SkGPipeReader reader(canvas); | 
|  | size_t bytesRead; | 
|  | SkGPipeReader::Status fStatus = reader.playback(fDataArray.begin(), | 
|  | fDataArray.count(), | 
|  | &bytesRead); | 
|  | SkASSERT(SkGPipeReader::kError_Status != fStatus); | 
|  | this->inval(NULL); | 
|  | } | 
|  |  | 
|  | private: | 
|  | bool fSync; | 
|  | SkTDArray<char> fDataArray; | 
|  | SkTCPClient* fSocket; | 
|  | typedef SampleView INHERITED; | 
|  | }; | 
|  |  | 
|  | /////////////////////////////////////////////////////////////////////////////// | 
|  |  | 
|  | static SkView* MyFactory() { return new NetPipeReaderView; } | 
|  | static SkViewRegister reg(MyFactory); |