Usermode/AxWin4 - Screen dimensions acquisition, speedup, window render
[tpg/acess2.git] / Usermode / Libraries / libaxwin4.so_src / ipc.cpp
1 /*
2  * AxWin4 Interface Library
3  * - By John Hodge (thePowersGang)
4  *
5  * ipc.c
6  * - IPC Abstraction
7  */
8 #include <axwin4/axwin.h>
9 #include "include/common.hpp"
10 #include "include/IIPCChannel.hpp"
11 #include "include/CIPCChannel_AcessIPCPipe.hpp"
12 #include <ipc_proto.hpp>
13 #include <algorithm>
14 #include <mutex>
15 #include <stdexcept>
16
17 #include <cstring>
18 #include <cstdio>
19
20 namespace AxWin {
21
22 IIPCChannel*    gIPCChannel;
23 ::std::mutex    glSyncReply;
24 bool    gSyncReplyValid;
25 CDeserialiser   gSyncReplyBuf;
26
27 extern "C" bool AxWin4_Connect(const char *URI)
28 {
29         _SysDebug("AxWin4_Connect('%s')", URI);
30         if( gIPCChannel ) {
31                 return false;
32         }
33         try {
34                 if( strncmp(URI, "ipcpipe://", 3+4+3) == 0 )
35                 {
36                         gIPCChannel = new CIPCChannel_AcessIPCPipe(URI+3+4+3);
37                 }
38                 else
39                 {
40                         _SysDebug("Unknown protocol");
41                         return false;
42                 }
43         }
44         catch( const ::std::exception& e )
45         {
46                 fprintf(stderr, "AxWin4_Connect: %s\n", e.what());
47                 return false;
48         }
49         return true;
50 }
51
52 extern "C" bool AxWin4_PeekEventQueue(void)
53 {
54         return false;
55 }
56
57 extern "C" bool AxWin4_WaitEventQueue(uint64_t Timeout)
58 {
59         return AxWin4_WaitEventQueueSelect(0, NULL, NULL, NULL, Timeout);
60 }
61
62 extern "C" bool AxWin4_WaitEventQueueSelect(int nFDs, fd_set *rfds, fd_set *wfds, fd_set *efds, uint64_t Timeout)
63 {
64         fd_set  local_rfds;
65         if( !rfds ) {
66                 FD_ZERO(&local_rfds);
67                 rfds = &local_rfds;
68         }
69         
70         int64_t select_timeout = Timeout;
71         int64_t *select_timeout_p = (Timeout ? &select_timeout : 0);
72         
73         nFDs = ::std::max(nFDs, gIPCChannel->FillSelect(*rfds));
74         _SysSelect(nFDs, rfds, wfds, efds, select_timeout_p, 0);
75         return gIPCChannel->HandleSelect(*rfds);
76 }
77
78 void SendMessage(CSerialiser& message)
79 {
80         gIPCChannel->Send(message);
81 }
82 void RecvMessage(CDeserialiser& message)
83 {
84         uint8_t id = message.ReadU8();
85         switch(id)
86         {
87         case IPCMSG_REPLY:
88                 // Flag reply and take a copy of this message
89                 if( gSyncReplyValid )
90                 {
91                         // Oh... that was unexpected
92                         _SysDebug("Unexpected second reply message %i", message.ReadU8());
93                 }
94                 else
95                 {
96                         gSyncReplyValid = true;
97                         gSyncReplyBuf = message;
98                 }
99                 break;
100         default:
101                 _SysDebug("TODO: RecvMessage(%i)", id);
102                 break;
103         }
104 }
105
106 CDeserialiser GetSyncReply(CSerialiser& request, unsigned int Message)
107 {
108         ::std::lock_guard<std::mutex>   lock(glSyncReply);
109         gSyncReplyValid = false;
110         // Send once lock is acquired
111         SendMessage(request);
112         
113         while( !gSyncReplyValid )
114         {
115                 // Tick along
116                 if( !AxWin4_WaitEventQueue(0) )
117                         throw ::std::runtime_error("Connection dropped while waiting for reply");
118         }
119         
120         uint8_t id = gSyncReplyBuf.ReadU8();
121         if( id != Message )
122         {
123                 _SysDebug("Unexpected reply message '%i', message.ReadU8()");
124         }
125         
126         return gSyncReplyBuf;
127 }
128
129 extern "C" void AxWin4_GetScreenDimensions(unsigned int ScreenIndex, unsigned int *Width, unsigned int *Height)
130 {
131         CSerialiser     req;
132         req.WriteU8(IPCMSG_GETGLOBAL);
133         req.WriteU16(IPC_GLOBATTR_SCREENDIMS);
134         req.WriteU8(ScreenIndex);
135         
136         CDeserialiser   response = GetSyncReply(req, IPCMSG_GETGLOBAL);
137         if( response.ReadU16() != IPC_GLOBATTR_SCREENDIMS ) {
138                 
139         }
140         
141         *Width = response.ReadU16();
142         *Height = response.ReadU16();
143         
144         _SysDebug("AxWin4_GetScreenDimensions: %i = %ix%i", ScreenIndex, *Width, *Height);
145 }
146
147 IIPCChannel::~IIPCChannel()
148 {
149 }
150
151 };      // namespace AxWin
152

UCC git Repository :: git.ucc.asn.au