1f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SampleCode.h" 2f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkView.h" 3f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkCanvas.h" 4f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkGradientShader.h" 5f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkGPipe.h" 6f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkSockets.h" 7f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com#include "SkOSMenu.h" 8f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 9ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com/** 10ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * A simple networked pipe reader 11ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * 12ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * This view will connect to a user specified server, in this case meaning any 13ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * Skia app that's has a SkTCPServer set up to broadcast its piped drawing data, 14ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * received all the data transmitted and attempt to reproduce the drawing calls. 15ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * This reader will only keep the latest batch of data. In order to keep up with 16ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * the server, which may be producing data at a much higher rate than the reader 17d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * is consuming, the reader will attempt multiple reads and only render the 18ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * latest frame. this behavior can be adjusted by changing MAX_READS_PER_FRAME 19ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com * or disabled by setting fSync to false 20ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com */ 21ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com 22ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com#define MAX_READS_PER_FRAME 12 23ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com 24f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.comclass NetPipeReaderView : public SampleView { 25f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.compublic: 26d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com NetPipeReaderView() { 27f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fSocket = NULL; 28ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com fSync = true; 29f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 30d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 31f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com ~NetPipeReaderView() { 32f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (fSocket) { 33f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com delete fSocket; 34f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 35f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fDataArray.reset(); 36f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 37f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com virtual void requestMenu(SkOSMenu* menu) { 38f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com menu->setTitle("Net Pipe Reader"); 39d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com menu->appendTextField("Server IP", "Server IP", this->getSinkID(), 40f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com "IP address"); 41f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com menu->appendSwitch("Sync", "Sync", this->getSinkID(), fSync); 42f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 43d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 44f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.comprotected: 45f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com static void readData(int cid, const void* data, size_t size, 46f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkSocket::DataType type, void* context) { 47f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com NetPipeReaderView* view = (NetPipeReaderView*)context; 48f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com view->onRead(data, size); 49f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 50d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 51f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com void onRead(const void* data, size_t size) { 52f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (size > 0) 53f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fDataArray.append(size, (const char*)data); 54f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 55d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 56f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com bool onQuery(SkEvent* evt) { 57f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (SampleCode::TitleQ(*evt)) { 58f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SampleCode::TitleR(evt, "Net Pipe Reader"); 59f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return true; 60f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 61f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return this->INHERITED::onQuery(evt); 62f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 63f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 64ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com bool onEvent(const SkEvent& evt) { 65f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkString s; 66ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com if (SkOSMenu::FindText(evt, "Server IP", &s)) { 67f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (NULL != fSocket) { 68f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com delete fSocket; 69f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 70f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fSocket = new SkTCPClient(s.c_str()); 71f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fSocket->connectToServer(); 72f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkDebugf("Connecting to %s\n", s.c_str()); 73f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return true; 74f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 75ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com if (SkOSMenu::FindSwitchState(evt, "Sync", &fSync)) 76f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return true; 77f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return this->INHERITED::onEvent(evt); 78f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 79d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 80f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com void onDrawContent(SkCanvas* canvas) { 81f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (NULL == fSocket) 82f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com return; 83f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 84f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (fSocket->isConnected()) { 85f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com int dataToRemove = fDataArray.count(); 86f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com if (fSync) { 87f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com int numreads = 0; 88d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com while (fSocket->readPacket(readData, this) > 0 && 89f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com numreads < MAX_READS_PER_FRAME) { 90ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com // at this point, new data has been read and stored, discard 91ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com // old data since it's not needed anymore 92ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com SkASSERT(fDataArray.count() > dataToRemove); 93f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fDataArray.remove(0, dataToRemove); 94f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com dataToRemove = fDataArray.count(); 95f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com ++numreads; 96f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 97ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com // clean up if max reads reached 98d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (numreads == MAX_READS_PER_FRAME && 99ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com fDataArray.count() > dataToRemove) 100ef7bdfac618f60e9edc9f42cd4661d563937e6d8yangsu@google.com fDataArray.remove(0, dataToRemove); 101f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 102f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com else { 103d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (fSocket->readPacket(readData, this) > 0) 104f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fDataArray.remove(0, dataToRemove); 105f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 106f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 107f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com else 108f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fSocket->connectToServer(); 109d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 110f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkGPipeReader reader(canvas); 111f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com size_t bytesRead; 112f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkGPipeReader::Status fStatus = reader.playback(fDataArray.begin(), 113f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com fDataArray.count(), 114f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com &bytesRead); 115f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkASSERT(SkGPipeReader::kError_Status != fStatus); 116f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com this->inval(NULL); 117f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com } 118f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 119f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.comprivate: 120f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com bool fSync; 121f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkTDArray<char> fDataArray; 122f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com SkTCPClient* fSocket; 123f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com typedef SampleView INHERITED; 124f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com}; 125f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 126f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com/////////////////////////////////////////////////////////////////////////////// 127f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.com 128f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.comstatic SkView* MyFactory() { return new NetPipeReaderView; } 129f3493f0e1f92a8a284adb93ecbf350401e1c7423yangsu@google.comstatic SkViewRegister reg(MyFactory); 130