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