UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
astat.cpp File Reference
#include "config_unix.h"
#include "config_win32.h"
#include "compat/platform_pipe.h"
#include <stdlib.h>
#include <stdio.h>
#include <thread>
#include <mutex>
#include <algorithm>
#include <string_view>
#include "astat.h"
Include dependency graph for astat.cpp:

Go to the source code of this file.

Classes

struct  ug_connection
 

Macros

#define MSG_DONTWAIT   0
 
#define MSG_NOSIGNAL   0
 

Functions

bool astat_parse_line (const char *str, double volpeak[CH_COUNT], double volrms[CH_COUNT])
 
static void parse_and_store (ug_connection &c, const char *str)
 
void ug_control_cleanup ()
 
void ug_control_connection_done (struct ug_connection *c)
 
struct ug_connection * ug_control_connection_init (int local_port)
 
bool ug_control_get_volumes (struct ug_connection *c, double peak[], double rms[], int *count)
 
void ug_control_init ()
 
static void worker (ug_connection &)
 
static ssize_t write_all (fd_t fd, const void *buf, size_t count)
 

Macro Definition Documentation

◆ MSG_DONTWAIT

#define MSG_DONTWAIT   0

Definition at line 22 of file astat.cpp.

Referenced by ug_control_connection_done().

◆ MSG_NOSIGNAL

#define MSG_NOSIGNAL   0

Definition at line 18 of file astat.cpp.

Referenced by write_all().

Function Documentation

◆ astat_parse_line()

bool astat_parse_line ( const char * str,
double volpeak[CH_COUNT],
double volrms[CH_COUNT] )

Definition at line 62 of file astat.cpp.

62 {
63 std::string_view prefix = "stats ARECV ";
64 if(strncmp(prefix.data(), str, prefix.size()) != 0)
65 return false;
66
67 const char *c = str + prefix.size();
68
69 int i = 0;
70 while(*c != '\0' && i < CH_COUNT){
71 int read_chars;
72 int ret = sscanf(c, "volrms%*d %lf volpeak%*d %lf %n",
73 &volrms[i], &volpeak[i], &read_chars);
74 c += read_chars;
75 i++;
76
77 if(ret != 2)
78 return false;
79 }
80
81 return true;
82}
#define CH_COUNT
Definition astat.h:3

References CH_COUNT.

Referenced by parse_and_store().

◆ parse_and_store()

static void parse_and_store ( ug_connection & c,
const char * str )
static

Definition at line 86 of file astat.cpp.

87{
88 double volpeak[CH_COUNT];
89 double volrms[CH_COUNT];
90 if (!astat_parse_line(str, volpeak, volrms)) {
91#ifdef ASTAT_DEBUG
92 fprintf(stderr, "Wrong line format!");
93#endif
94 return;
95 }
96
97 lock_guard<mutex> lk(c.lock);
98 for (int i = 0; i < CH_COUNT; i++) {
99 c.volpeak[i] = std::max(c.volpeak[i], volpeak[i]);
100 c.volrms[i] = (volrms[i] * c.sample_count + volrms[i]) / (c.sample_count + 1);
101 }
102 c.sample_count += 1;
103}
bool astat_parse_line(const char *str, double volpeak[CH_COUNT], double volrms[CH_COUNT])
Definition astat.cpp:62
int sample_count
Definition astat.cpp:52
double volpeak[CH_COUNT]
Definition astat.cpp:50
mutex lock
Definition astat.cpp:53
double volrms[CH_COUNT]
Definition astat.cpp:51

References astat_parse_line(), CH_COUNT, ug_connection::lock, ug_connection::sample_count, ug_connection::volpeak, and ug_connection::volrms.

Referenced by worker().

Here is the call graph for this function:

◆ ug_control_cleanup()

void ug_control_cleanup ( )

Definition at line 255 of file astat.cpp.

255 {
256#ifdef _WIN32
257 WSACleanup();
258#endif
259}

◆ ug_control_connection_done()

void ug_control_connection_done ( struct ug_connection * c)

Definition at line 205 of file astat.cpp.

205 {
206 if(!c){
207 return;
208 }
209 c->should_exit = true;
210 char ch = 0;
211 int ret = send(c->should_exit_fd[1], &ch, 1, MSG_DONTWAIT);
212 if (ret == -1) {
213 perror("ug_control_connection_done send");
214 }
215 c->t.join();
218 CLOSESOCKET(c->fd);
219 delete c;
220}
#define MSG_DONTWAIT
Definition astat.cpp:22
#define CLOSESOCKET
void platform_pipe_close(fd_t pipe)
fd_t should_exit_fd[2]
Definition astat.cpp:56
thread t
Definition astat.cpp:57
volatile bool should_exit
Definition astat.cpp:55

References CLOSESOCKET, ug_connection::fd, MSG_DONTWAIT, platform_pipe_close(), ug_connection::should_exit, ug_connection::should_exit_fd, and ug_connection::t.

Here is the call graph for this function:

◆ ug_control_connection_init()

struct ug_connection * ug_control_connection_init ( int local_port)
Parameters
local_portUltraGrid control port to connect to

Definition at line 177 of file astat.cpp.

177 {
178 int fd = socket(AF_INET6, SOCK_STREAM, 0);
179 if (fd == -1) {
180 return nullptr;
181 }
182 fd_t should_exit_fd[2];
183 struct sockaddr_in6 sin;
184 memset(&sin, 0, sizeof sin);
185 sin.sin6_family = AF_INET6;
186 sin.sin6_port = htons(local_port);
187 sin.sin6_addr = in6addr_loopback;
188
189 if (connect(fd, (const sockaddr*) &sin, sizeof sin) == -1) {
190 CLOSESOCKET(fd);
191 return NULL;
192 }
193
194 char stats_on[] = "stats on\r\n";
195 if (write_all(fd, stats_on, sizeof stats_on) != sizeof stats_on) {
196 CLOSESOCKET(fd);
197 return NULL;
198 }
199
200 platform_pipe_init(should_exit_fd);
201
202 return new ug_connection{fd, should_exit_fd};
203}
static ssize_t write_all(fd_t fd, const void *buf, size_t count)
Definition astat.cpp:30
int fd_t
int platform_pipe_init(fd_t p[2])

References CLOSESOCKET, ug_connection::fd, platform_pipe_init(), ug_connection::should_exit_fd, and write_all().

Here is the call graph for this function:

◆ ug_control_get_volumes()

bool ug_control_get_volumes ( struct ug_connection * c,
double peak[],
double rms[],
int * count )
Parameters
peakReturns peak volume for 2 channels. Must be array of 2 doubles.
rmsReturns RMS volume for 2 channels. Must be array of 2 doubles.
Return values
falseif connection was closed

Definition at line 227 of file astat.cpp.

227 {
228 if (!c)
229 return false;
230
231 lock_guard<mutex> lk(c->lock);
232
233 if (c->connection_lost) {
234 return false;
235 }
236
237 memcpy(peak, c->volpeak, sizeof c->volpeak);
238 memcpy(rms, c->volrms, sizeof c->volrms);
239 *count = c->sample_count;
240
241 std::fill_n(c->volpeak, sizeof(c->volpeak)/sizeof(*c->volpeak), -INFINITY);
242 memset(c->volrms, 0, sizeof c->volrms);
243 c->sample_count = 0;
244
245 return true;
246}
int count
Definition hd-rum.c:44
bool connection_lost
Definition astat.cpp:59

References ug_connection::connection_lost, count, ug_connection::lock, ug_connection::sample_count, ug_connection::volpeak, and ug_connection::volrms.

◆ ug_control_init()

void ug_control_init ( )

Definition at line 248 of file astat.cpp.

248 {
249#ifdef _WIN32
250 WSADATA wsa;
251 WSAStartup(MAKEWORD(2,2), &wsa);
252#endif
253}

◆ worker()

static void worker ( ug_connection & c)
static

Definition at line 105 of file astat.cpp.

106{
107 char line[10000] = "";
108 while (!c.should_exit) {
109 char buf[9000] = "";
110
111 fd_set fds;
112 FD_ZERO(&fds);
113 FD_SET(c.fd, &fds);
114 FD_SET(c.should_exit_fd[0], &fds);
115 fd_t nfds = std::max<fd_t>(c.fd, c.should_exit_fd[0]) + 1;
116
117 int rc = select(nfds, &fds, NULL, NULL, NULL);
118 if (rc <= 0) {
119 continue;
120 }
121
122 if (FD_ISSET(c.should_exit_fd[0], &fds)) {
123 break;
124 }
125
126 ssize_t ret = recv(c.fd, buf, sizeof buf, 0);
127 if (ret == 0) { // connection was closed
128 lock_guard<mutex> lk(c.lock);
129 c.connection_lost = true;
130#ifdef ASTAT_DEBUG
131 fprintf(stderr, "Connection lost!\n");
132#endif
133 break;
134 }
135
136 if (ret < 0) {
137#ifdef _WIN32
138 int err = WSAGetLastError();
139 if(err == WSAECONNRESET){
140 lock_guard<mutex> lk(c.lock);
141 c.connection_lost = true;
142#ifdef ASTAT_DEBUG
143 fprintf(stderr, "Connection lost!\n");
144#endif
145 break;
146 }
147 printf("recv: %d \n", WSAGetLastError());
148#else
149 perror("recv");
150#endif
151 continue;
152 }
153
154 assert(ret + strlen(line) < sizeof line - 1); // TODO...
155 memcpy(line + strlen(line), buf, ret);
156 // process individual lines
157 while (strchr(line, '\n')) {
158 char *next = strchr(line, '\n') + 1;
159 *strchr(line, '\n') = '\0';
160
161 // process one line
162 if (strstr(line, "stats ARECV") == line) { // only process those lines that belong to us
163 parse_and_store(c, line);
164 }
165
166 // move the rest
167 size_t rest_len = strlen(next);
168 memmove(line, next, rest_len);
169 memset(line + rest_len, 0, sizeof line - rest_len);
170 }
171 }
172}
static void parse_and_store(ug_connection &c, const char *str)
Definition astat.cpp:86

References ug_connection::connection_lost, ug_connection::fd, ug_connection::lock, parse_and_store(), ug_connection::should_exit, and ug_connection::should_exit_fd.

Here is the call graph for this function:

◆ write_all()

static ssize_t write_all ( fd_t fd,
const void * buf,
size_t count )
static

Definition at line 30 of file astat.cpp.

31{
32 char *p = (char *) buf;
33 size_t rest = count;
34 ssize_t w = 0;
35
36 while (rest > 0 && (w = send(fd, p, rest, MSG_NOSIGNAL)) >= 0) {
37 p += w;
38 rest -= w;
39 }
40
41 if (rest > 0)
42 return w;
43 else
44 return count;
45}
#define MSG_NOSIGNAL
Definition astat.cpp:18

References count, and MSG_NOSIGNAL.

Referenced by ug_control_connection_init().