CARMA C++
im_monitor_stream.h
1 #ifndef im_monitor_stream_h
2 #define im_monitor_stream_h
3 
4 /*-----------------------------------------------------------------------
5  * This module provides a generic stream interface for reading frame grabber
6  * images from a source. Supported sources include a network
7  * connection to the control program.
8  *
9  * The internals of a stream are logically split into two parts, a
10  * local consumer and a potentially remote supplier. Given that the
11  * supplier can be in a separate process, messaging via either
12  * non-blocking or blocking I/O is used to dispatch control messages
13  * to, and receive data from a given supplier. The only time that
14  * non-blocking I/O is not an option is when the stream makes a
15  * connection to a new supplier. At this time, information, such as
16  * the register map of the supplier and buffer size information is
17  * read from the supplier using blocking I/O.
18  *
19  * The following datatype provides an opaque handle for all stream
20  * types. Its internals are private to im_monitor_stream.c.
21  */
22 typedef struct ImMonitorStream ImMonitorStream;
23 
24 /*
25  * Create a new ImMonitorStream object and attach it to a control
26  * program on a given host. The host argument should contain
27  * the name or internet address of the computer on which the
28  * control program is running.
29  *
30  * When successful this function returns the new ImMonitorStream
31  * object. On failure it returns NULL.
32  */
33 ImMonitorStream *new_NetImMonitorStream(char *host);
34 
35 /*
36  * The following function closes and deletes a monitor stream.
37  * Note that del_ImMonitorStream() is idempotent (ie. it returns NULL
38  * to represent a deleted stream, and can safely take NULL as an
39  * argument).
40  */
41 ImMonitorStream *del_ImMonitorStream(ImMonitorStream *ims);
42 
43 /*-----------------------------------------------------------------------
44  * Stream method functions.
45  *
46  * The following functions should only be used while a stream is
47  * connected to a supplier.
48  *---------------------------------------------------------------------*/
49 
50 /*
51  * The function that reads data from the supplier can be told to wait
52  * for a complete record to be received, or to read as much as possible
53  * without blocking, then return with an indication that a future call
54  * will be necessary to retrieve the remaining data. The following
55  * values are returned by said function to indicate the state of the
56  * read operation.
57  */
58 typedef enum { /* Frame-reader read status */
59  IMS_READ_ENDED, /* The end of the stream has been reached */
60  IMS_READ_AGAIN, /* The read operation is incomplete (dowait=0) */
61  IMS_READ_DONE /* A new image has been read */
62 } ImsReadState;
63 
64 /*
65  * When sending a control message to the supplier, one first submits
66  * the message to be packed for transmission by calling the
67  * appropriate submittal function, then calls ims_send_msg() to
68  * transmit the message. When calling ims_send_msg() one can ask to have
69  * the message sent in its entirety before returning, or to have as much
70  * as possible sent without blocking. In the latter case, completion
71  * of the send operation must be completed by subsequent calls to
72  * ims_send_msg().
73  *
74  * Note that while a send operation is incomplete the values submitted
75  * via intervening calls to ims_queue_regset() and/or ims_queue_interval()
76  * will be queued for re-submision when the current send
77  * completes. ims_send_msg() will not return IMS_SEND_DONE until all
78  * such transactions have been completed.
79  *
80  * The following values are returned by ims_send_msg() to indicate the
81  * state of the send operation.
82  */
83 typedef enum { /* Frame-reader write status */
84  IMS_SEND_ERROR, /* An unrecoverable error occurred */
85  IMS_SEND_AGAIN, /* The send operation is incomplete (dowait=0) */
86  IMS_SEND_DONE /* The message has been sent */
87 } ImsSendState;
88 
89 /*
90  * Incrementally read the next frame grabber image from the established
91  * data supplier. If dowait==0, retrieval of each
92  * image may require multiple calls to this function. In such cases
93  * select() can be used to wait for the arrival of more data. See
94  * ims_select_fd() below for details.
95  */
96 ImsReadState ims_read_image(ImMonitorStream *ims, int dowait);
97 
98 /*
99  * Incrementally send a message, previously submitted via a
100  * call to ims_queue_interval(), ims_queue_regset() or ims_queue_rewind,
101  * to the supplier. Multiple calls to this function may be required if
102  * dowait==0. In such cases select() can be used to wait for the
103  * output channel to free up. See ims_select_fd() for details.
104  */
105 ImsSendState ims_send_msg(ImMonitorStream *ims, int dowait);
106 
107 /*
108  * Return a file descriptor that can be used with select() to
109  * determine when more data is available, or when the output
110  * channel to the supplier is ready to accept more data. If the
111  * stream isn't connected, -1 will be returned.
112  *
113  * WARNING: This file descriptor may change after any call to
114  * ims_read_image(), so be sure to call ims_select_fd()
115  * before every call to select().
116  */
117 int ims_select_fd(ImMonitorStream *ims);
118 
119 /*-----------------------------------------------------------------------
120  * The rest of this file regards implementation of new stream sources.
121  *
122  * The specific implementation of a particular stream source is
123  * implemented through the following method functions, plus an
124  * anonymous implementation object allocated by the stream source.
125  *---------------------------------------------------------------------*/
126 
127 /*
128  * To create an unconnected monitor stream call new_ImMonitorStream().
129  */
130 ImMonitorStream *new_ImMonitorStream(void);
131 
132 
133 /*.......................................................................
134  * The following method is called upon to read all or part of the
135  * next frame of registers. It should behave like its generic
136  * counterpart described above.
137  */
138 #define IMS_READ_IMAGE(fn) ImsReadState (fn)(ImMonitorStream *ims, int dowait)
139 
140 /*.......................................................................
141  * Where provided, the following optional method is called upon to
142  * send part or all of the most recently packed output message.
143  */
144 #define IMS_SEND_MSG(fn) ImsSendState (fn)(ImMonitorStream *ims, int dowait)
145 
146 /*.......................................................................
147  * The following method returns a file descriptor for use in select() to
148  * see when the stream is ready for reading or writing. Note that the
149  * select() user is expected to call this before each use of select().
150  * This allows the fd to change with time (for example, the file
151  * monitor will read across file boundaries, so the fd may well change).
152  */
153 #define IMS_SELECT_FD(fn) int (fn)(ImMonitorStream *ims)
154 
155 /*.......................................................................
156  * The following method is called to delete the stream-specific
157  * implementation context.
158  */
159 #define IMS_DESTRUCTOR(fn) void *(fn)(void *context)
160 
161 /*.......................................................................
162  * The following function is used to connect a given stream source to
163  * a monitor stream object. It requires the register map read from the
164  * supplier, a stream-specific context object + its destructor, and
165  * the above method functions. It returns non-zero if the call fails.
166  */
167 int open_ImMonitorStream(ImMonitorStream *ims, void *context,
168  IMS_DESTRUCTOR(*del_fn),
169  IMS_READ_IMAGE(*read_fn), IMS_SEND_MSG(*send_fn),
170  IMS_SELECT_FD(*fd_fn));
171 /*
172  * The above method functions can retrieve the context object that
173  * was registered with open_ImMonitorStream(), by calling the following
174  * function.
175  */
176 void *ims_SourceContext(ImMonitorStream *ims);
177 
178 /*
179  * The above method functions can retrieve the image buffer, by calling the
180  * following function.
181  */
182 unsigned short *ims_get_image(ImMonitorStream *ims);
183 
184 /*
185  * The following function is used to close a ImMonitorStream. This
186  * is done for you by del_ImMonitorStream(). Also open_ImMonitorStream()
187  * calls this function before connecting a stream to a new supplier.
188  * Note that close_ImMonitorStream() is idempotent.
189  */
190 void close_ImMonitorStream(ImMonitorStream *ims);
191 
192 
193 #endif