Returning from SIGIO handler prevents future SIGIO handling

I am trying to read from a serial port only when there is data available. I used fcntl to attach a SIGIO signal to the deviceDescriptor. It works. Pressing the X10 powerhouse palmpad remote (which generates the serial output via a W800 RF receiver ), causes SIGIO and runs sigaction. Pressing the remote again, causes another SIGIO signal and runs sigaction. However, I need to return program control to main after sigaction handler executes. An infinite loop in main needs to process house_c and provide notifications based on its value. This is the part I can't figure out. If I use setjmp and longjmp, control returns to main but the program no longer responds to SIGIO ( or perhaps no SIGIO's are generated any more, or they are generated but not linked to my program pid). If I dont use setjmp and longjmp, the program continues to react to serial output which continues to invoke the signal handler with each keypress but it is limited to what can be run in the handler.

How do I properly return to main and be able to process future SIGIO's.

Thanks,
Chris

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   main.cpp
 * Author: cmisip
 *
 * Created on March 5, 2017, 8:19 AM
 */

#include <cstdlib>
#include <cstdlib>
#include <iostream>
#include <bitset>
#include <termios.h> 
#include <sys/file.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <cstring>
#include <errno.h> 
#include <algorithm>
#include <setjmp.h>


#define SUCCESS  1
#define ERR      0
#define BAUD_RATE        B4800

int deviceDescriptor;
int n, fl;
uint8_t c[4];

char const * device="/dev/ttyUSB0";
char house_c;

jmp_buf return_to_start;


int Connect(char const *device) {
    if(device == NULL) return ERR;

    struct termios tty;

    // Try to open the device
    if((deviceDescriptor = open(device, O_RDWR | O_NDELAY)) == -1) {
        return ERR;
    }

    tcgetattr(deviceDescriptor, &tty);
    
    cfmakeraw(&tty);
    cfsetspeed(&tty, 4800);
    
    tcsetattr(deviceDescriptor, TCSADRAIN, &tty);
    tcflush(deviceDescriptor, TCIOFLUSH);
    
    tty.c_cflag &= ~CSTOPB; // 1 stop bit
    
    
    /* eat any queued characters */
    while ((n = read(deviceDescriptor, &c[0], 1)) == 1) {
		/* nothing */ ;
    }
    
    tty.c_cflag     = CREAD | CS8 | CLOCAL;
    
    
    tcsetattr(deviceDescriptor, TCSANOW, &tty);
    
    fl = fcntl(deviceDescriptor, F_GETFL);
    fl &= ~O_NONBLOCK;
    fcntl(deviceDescriptor, F_SETFL, fl);
    
    //this is required for kernel to send SIGIO commands to this process asynchronously
    fcntl(deviceDescriptor, F_SETOWN, getpid());
    fcntl(deviceDescriptor, F_SETFL, FASYNC);
    
    return deviceDescriptor;
}

int Disconnect(void) {
    // Check if not connected
    if(deviceDescriptor == 0) {
        return ERR;
    }

    if(close(deviceDescriptor) == -1) {
        return ERR;
    }

    deviceDescriptor = 0;
    return SUCCESS;
}

void sigalarm(int sig)
{
    std::cout << "SIGIO detected " << std::endl;
    house_c=(char)(house_c+1);
    longjmp(return_to_start, 1); 
}

int main(int argc, char** argv) {
 
    Connect(device);
    
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;	
    sa.sa_handler = sigalarm;
    sigaction(SIGIO,&sa,NULL);
   
    sa.sa_restorer = NULL;
    
    
    if (setjmp(return_to_start)) {
            std::cout << "Returned to start " << std::endl;
     
    }
    
    
    
    for (;;) {  //I NEED the program to return here after each handling of SIGIO via sigalarm.
                  //whilst being able to continue to process SIGIO signals
     sleep(1);
        std::cout << "House " << house_c << std::endl;
    } 
        
    Disconnect();
    return 0;
}

Last edited on
I got it working thus far. The only problem now is that I get multiple SIGIO's and longjmps. Is it possible to have only one SIGIO for any number of characters available on the serial port? Can SIGIO be blocked temporarily?

Thanks,
Chris

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   main.cpp
 * Author: cmisip
 *
 * Created on March 5, 2017, 8:19 AM
 */

#include <cstdlib>
#include <cstdlib>
#include <iostream>
#include <bitset>
#include <termios.h> 
#include <sys/file.h>
#include <stdint.h>
#include <unistd.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <cstring>
#include <errno.h> 
#include <algorithm>
#include <setjmp.h>
#include <sys/ioctl.h>


#define SUCCESS  1
#define ERR      0
#define BAUD_RATE        B4800

//HOUSE CODES
#define A           0b00000110
#define B           0b00001110
#define C           0b00000010
#define D           0b00001010
#define E           0b00000001
#define F           0b00001001
#define G           0b00000101
#define H           0b00001101
#define I           0b00000111
#define J           0b00001111
#define K           0b00000011
#define L           0b00001011
#define M           0b00000000
#define N           0b00001000
#define O           0b00000100
#define P           0b00001100


//the house_code returned will be index, not letter
static unsigned char house_code[16] = {
A, B, C, D, E, F, G, H,
I, J, K, L, M, N, O, P, };


int deviceDescriptor;
int n, fl;
uint8_t c[4];

char const * device="/dev/ttyUSB0";
char house_c;

static jmp_buf return_to_start;
std::string command="";
volatile bool detected=false;


int Connect(char const *device) {
    if(device == NULL) return ERR;

    struct termios tty;

    // Try to open the device
    if((deviceDescriptor = open(device, O_RDWR | O_NDELAY)) == -1) {
        return ERR;
    }

    tcgetattr(deviceDescriptor, &tty);
    
    cfmakeraw(&tty);
    cfsetspeed(&tty, 4800);
    
    tcsetattr(deviceDescriptor, TCSADRAIN, &tty);
    tcflush(deviceDescriptor, TCIOFLUSH);
    
    tty.c_cflag &= ~CSTOPB; // 1 stop bit
    
    
    /* eat any queued characters */
    while ((n = read(deviceDescriptor, &c[0], 1)) == 1) {
		/* nothing */ ;
    }
    
    tty.c_cflag     = CREAD | CS8 | CLOCAL;
    
    
    tcsetattr(deviceDescriptor, TCSANOW, &tty);
    
    fl = fcntl(deviceDescriptor, F_GETFL);
    fl &= ~O_NONBLOCK;
    fcntl(deviceDescriptor, F_SETFL, fl);
    
    //this is required for kernel to send SIGIO commands to this process asynchronously
    fcntl(deviceDescriptor, F_SETOWN, getpid());
    fcntl(deviceDescriptor, F_SETFL, FASYNC);
    
    return deviceDescriptor;
}

int Disconnect(void) {
    // Check if not connected
    if(deviceDescriptor == 0) {
        return ERR;
    }

    if(close(deviceDescriptor) == -1) {
        return ERR;
    }

    deviceDescriptor = 0;
    return SUCCESS;
}


int ReceiveByte(unsigned char  &byte) {
    usleep(10000);
    return (read(deviceDescriptor, &byte, 1) == 1 ? SUCCESS : ERR);
}


static unsigned char lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };


uint8_t reverse(uint8_t n) {
   // Reverse the top and bottom nibble then swap them.
   return (lookup[n&0b1111] << 4) | lookup[n>>4];
}


//rightmost is pos 0 
bool IsBitSet(uint8_t b, int pos)
{
   return (b & (1 << pos)) != 0;
}

void process(){
      
    std::cout << "Processing " << std::endl;
    for (int i = 0;  i < 4; i++) {
       ReceiveByte(c[i]);
    }
    
    
    if ( ( (c[0] & c[1]) == 0) && ((c[2] & c[3]) == 0) ) {
        //std::cout << "Reverse,  " ;
        for (int i = 0;  i < 4; i++) {
            c[i] = reverse(c[i]);
        }
        
        //std::cout << "Reorder, " ;
        uint8_t t[4]= { c[0], c[1], c[2], c[3] };
        c[0]=t[2]; c[1]=t[3]; c[2]=t[0]; c[3]=t[1];
    }    
    
    //House codes for Units 9-16 have a 1 on bit 5 (counting from rightmost which is bit 0)
    //So check if bit 5 is 1
    bool upper_code=IsBitSet(c[2], 5);
    
    int x;
    uint8_t h=c[2];
    //Get the house code and print it
    if (IsBitSet(c[2], 5))  // zero out the 5th bit to get the right house_code
         h ^= 1 << 5; 
         
    x = std::distance(house_code, std::find(house_code, house_code + 16, h )); 
        
    //Calculate the unit code, remember that the actual unit code is plus 1 of the unit value
    std::bitset<8>unit(0);
    unit[4]=0;
    unit[5]=0;
    unit[6]=0;
    unit[7]=0;
    
    //bit 0 of unit number is bit 3 of byte 1
    unit[0]=IsBitSet(c[0], 3);
    //bit 1 of unit number is bit 4 of byte 1
    unit[1]=IsBitSet(c[0], 4);
    //bit 2 of unit number is bit 1 of byte 1
    unit[2]=IsBitSet(c[0], 1);
    //bit 4 of unit number is bit 5 of byte 3
    unit[3]=IsBitSet(c[2], 5);
    
    //Convert the housecode to letter
    house_c = (char)('A' + x );
      
    
    //Get the command on or off, this is bit 2 of byte 1 which is 1 for OFF
    if (IsBitSet(c[0],2)) 
      command="OFF";
    else
      command="ON";
    
    std::cout << " | " << house_c << " " << (int)unit.to_ulong() +1 << " "  << command << std::endl;
    return;
}


void sigalarm(int sig)
{
    std::cout << "SIGIO detected " << std::endl;
    detected=true;
    
  
    siglongjmp(return_to_start, 1); 
}

int serialDataAvail (const int fd)
{
  int result ;

  if (ioctl (fd, FIONREAD, &result) == -1)
    return -1 ;

  return result ;
}

void dummy(int sig){
    
}

int main(int argc, char** argv) {
 
    Connect(device);
    
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;	
    sa.sa_handler = sigalarm;
    
    sigaction(SIGIO,&sa,NULL);
   
    
    if (sigsetjmp(return_to_start,1)) {
            std::cout << "Returned to start " << std::endl;
    }
    
    for (;;) { 
                
     sleep(1);
     if (detected) {
         do  {
         process();
         } while (serialDataAvail (deviceDescriptor));
         detected=false;
     }
        std::cout << "House " << house_c << std::endl;
    } 
        
    Disconnect();
    return 0;
}

> Can SIGIO be blocked temporarily?

sigaction() with the flag SA_RESETHAND would deliver only the first signal
Once all the characters available are read, reinstall the signal handler.

https://www.freebsd.org/cgi/man.cgi?query=sigaction&apropos=0&sektion=0&manpath=FreeBSD+10.2-RELEASE&arch=default&format=html
Trying a bunch of things at this time. With resethand or with manually setting the handler to SIG_IGN, I cant figure out why the program runs fine on one run and then on another run it outputs the "I/O Possible" and then terminates.

I made some extensive changes and the latest program displays the "I/O Possible" and terminates unless I run the code from the earlier post first. After that, the latest version with the extensive changes would run.

I am looking into fcntl at this time. Will post what I find out.

Thanks,
Chris
I have working code again. I think the problem was sigsetjmp needed to run right away otherwise siglongjmp has nowhere to go when an immediate SIGIO occurs. I moved the initialization of the serial device and audio device after sigsetjmp and that seems to have fixed the problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <setjmp.h>
#include "Connect.h"
#include "Tools.h"
#include "Audio.h"
#include <chrono>

char const * device="/dev/ttyUSB0";
static jmp_buf return_to_start;
volatile sig_atomic_t detected=false;
bool reset=true;
int post_bytes;

struct sigaction sa, oldsa;

std::chrono::high_resolution_clock::time_point start_time;
std::chrono::high_resolution_clock::time_point current_time;

audio_sample dining_room, living_room, kitchen, front_hallway;

void sigalarm(int sig)
{
   
       detected=true;
       std::cout << "SIGIO detected " << std::endl;
       siglongjmp(return_to_start, 1);
}




int main(int argc, char** argv) {
    //THIS needs to run first, otherwise an immediate SIGIO will have nowhere to jump to. So INIT routines for serial and audio in the else branch 
    if (sigsetjmp(return_to_start,1)) {
            std::cout << "Returned to start " << std::endl;
            sa.sa_handler = SIG_IGN;  //No more SIGI_IO's until we processed all data
            if (sigaction(SIGIO, &sa, NULL) < 0) {
		perror ("sigaction");
		return 1;
            } 
            
    } else {  //RUN INIT ROUTINES
                 
          //INSTALL SIGIO handler
          memset(&sa, 0, sizeof(sa));
          sigemptyset(&sa.sa_mask);
          sa.sa_flags = 0;	
          sa.sa_handler = sigalarm;
          sa.sa_restorer = NULL;

          if (sigaction(SIGIO, &sa, &oldsa) < 0) {
		perror ("sigaction");
		return 1;
          }
           /* Serial */
          Connect(device);
           /* Audio */
          ao_initialize();
    
          driver = ao_default_driver_id();
          int err = mpg123_init();
          if(err != MPG123_OK) {
               fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
          }
         
          //audio samples need to be a certain minimum length
          dining_room=audio_sample("samples/Dining_Room.mp3"); 
          living_room=audio_sample("samples/Living_Room.mp3");
          kitchen=audio_sample("samples/Kitchen_Nook.mp3");
          front_hallway=audio_sample("samples/Front_Hallway.mp3");
    
          start_time = std::chrono::high_resolution_clock::now();
    }
    
    
    std::cout << "Waiting for Serial Data" << std::endl;
    post_bytes=0;
    
    for (;;) { 
                
     sleep(1);
     if (detected) {
             
             if (serialDataAvail() > post_bytes) { //received another stream of serial data before we read everything in the buffer
                reset=true; 
                std::cout << "MORE data " << std::endl;
             } 
              
             if (serialDataAvail() % 4 == 0 ) { //serial data must be in set of 4 bytes, unaligned read    
                   std::cout << "Serial data BEFORE process " << serialDataAvail() << std::endl;
                   process();
                   post_bytes=serialDataAvail();
                   std::cout << "Serial data AFTER process " << post_bytes << std::endl;
             } else
                 serialFlush();
             
            if (serialDataAvail() == 0) {
                reset=true;
                detected=false;
                sa.sa_handler = sigalarm;
          
                if (sigaction(SIGIO, &sa, NULL) < 0) {
		     perror ("sigaction");
		     return 1;
            }
           }    
     } 
          //Running queue for audio notifications
          if (mqueue.size() > 0) {
              current_time = std::chrono::high_resolution_clock::now();
              auto elapsed_time=std::chrono::duration_cast<std::chrono::seconds>(current_time - start_time).count();
              if  (elapsed_time > 3) {
                 std::pair<char,int> lastpair=mqueue.front();
                 std::cout << "QUEUE : size : "<< mqueue.size() << " | " << mqueue.front().first << " " << mqueue.front().second << std::endl;
                 mqueue.pop();
                 
              if ((lastpair.first == 'A' ) && (lastpair.second == 1)) {
                 std::cout << "DINING" << std::endl;
                 dining_room.play();
              }
             
              else if ((lastpair.first == 'E' ) && (lastpair.second == 1)) {
                 living_room.play();
                 std::cout << "LIVING ROOM" << std::endl;
              }
             
              else if ((lastpair.first == 'F' ) && (lastpair.second == 1)) {
                 front_hallway.play();
                 std::cout << "FRONT HALL" << std::endl;
              }

              start_time = std::chrono::high_resolution_clock::now();
             } 
          } 
              
      
      if (kbhit()) {
          std::cout << "KEY pressed.. quitting" << std::endl;
          break;
      };
    }
    
    //EXITED the loop, restore the signal handler to OS default
    if (sigaction(SIGIO, &oldsa, NULL) < 0) {
		perror ("sigaction");
		return 1;
    }
    
    Disconnect();
    
    ao_close(dev);
    mpg123_exit();
    ao_shutdown();
    
    return 0;
}



I'm sure I will run into bugs on testing. If you have any suggestions to improve please let me know.

Thanks,
Chris
Getting segfaults when I mash the x10 powerhouse palmpad remote thus flooding the w800 serial port with serial bytes. I think the array I read the bytes into somehow get undefined in the middle of the process() function as the signal handling yanks execution out of the function and then it tries to return to it. I am working on an alternate solution.

Chris

I was able to get rid of the segfault. The solution was to use sigprocmask and remove the siglongjmp. The signal handler is now only setting one sig_atomic_t value. This part seems to be working well. I will keep testing. If only I could figure out why libao will only play the audio once, but I will post that question in another thread.
Thanks,
Chris


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   main.cpp
 * Author: cmisip
 *
 * Created on March 5, 2017, 8:19 AM
 */
#include "Connect.h"
#include "Tools.h"
#include "Audio.h"
#include <chrono>
#include <stdlib.h> 

char const * device="/dev/ttyUSB0";
volatile sig_atomic_t timeout=0;

bool cleared=true;
bool stream_pause=false;

struct sigaction sa, oldsa;
sigset_t block_alarm;

std::chrono::high_resolution_clock::time_point start_time;
std::chrono::high_resolution_clock::time_point current_time;

audio_sample dining_room, living_room, kitchen, front_hallway;

void sigalarm(int sig)
{
       std::cout << "SIGIO detected " << std::endl;
       timeout=0;
}

void clear_d(){
    if (!cleared) {
             std::cout << "Clearing d " << std::endl;
             for (int i = 0;  i < 4; i++) {
               d[i] = 0;
             }
             cleared=true;
    }
}


int main(int argc, char** argv) {

    /* Initialize the signal mask. */
    sigemptyset (&block_alarm);
    sigaddset (&block_alarm, SIGIO);
        
    //INSTALL SIGIO handler
    memset(&sa, 0, sizeof(sa));
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;	
    sa.sa_handler = sigalarm;

    if (sigaction(SIGIO, &sa, &oldsa) < 0) {
	perror ("sigaction");
        return 1;
    }
  
    /* Serial */
    Connect(device);
          
    /* Audio */
    ao_initialize();
    
    driver = ao_default_driver_id();
    int err = mpg123_init();
    if(err != MPG123_OK) {
          fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
    }
         
    //audio samples need to be a certain minimum length
    dining_room=audio_sample("samples/Dining_Room.mp3"); 
    living_room=audio_sample("samples/Living_Room.mp3");
    kitchen=audio_sample("samples/Kitchen_Nook.mp3");
    front_hallway=audio_sample("samples/Front_Hallway.mp3");
    
    
    start_time = std::chrono::high_resolution_clock::now();
    
    //initialize d for comparing previous and current 4 byte serial data
    for (int i = 0;  i < 4; i++) {
               d[i] = 0;
    }
    
    sleep(4); //headstart for first audio announcement
    std::cout << "Waiting for Serial Data" << std::endl;
    
    for (;;) { 
                
      sleep(1);
      timeout++;
      if ((timeout > 1) && (serialDataAvail() >3)) {  //SIGIO signals stopped and there are pending bytes to read 
          stream_pause=true;
      }
      
      if (timeout > 10)
           timeout=2;  //timeout will always be greater than 1 unless a SIGIO happens 
      
      
      if (stream_pause) {
             cleared=false;
             std::cout << "DETECTED " << serialDataAvail() << std::endl; 
             sigprocmask (SIG_BLOCK, &block_alarm, NULL);  // block, remaining SIGIO's queued 
             if (serialDataAvail() > 3) {
                   std::cout << "Serial data BEFORE process " << serialDataAvail() << std::endl;
                   process();  //read and process in 4 byte chunks
                   std::cout << "Serial data AFTER process " << serialDataAvail() << std::endl;
             } 
             
             if (serialDataAvail() == 0) {     
                 std::cout << "No more bytes to process" << std::endl;
                 stream_pause=false;
                 clear_d();
             } 
             
             sigprocmask (SIG_UNBLOCK, &block_alarm, NULL); //unblock, all queued SIGIO's released
             
      } 
    
      if (kbhit()) {
          std::cout << "KEY pressed.. quitting" << std::endl;
          break;
      };
      
      std::pair<char,int> lastpair {'Z',1};
      
      if (mqueue.size() > 0) {
              current_time = std::chrono::high_resolution_clock::now();
             
              do  {  
                 lastpair=mqueue.front();
                 std::cout << "QUEUE : size : "<< mqueue.size() << " | " << mqueue.front().first << " " << mqueue.front().second << std::endl;
                 mqueue.pop();
      
              //placeholder for pushover text notification   
              if ((lastpair.first == 'D' ) && (lastpair.second == 1)) {
                 std::cout << "DINING--------------------------------------------------------------" << std::endl;
              }
             
              else if ((lastpair.first == 'E' ) && (lastpair.second == 1)) {
                  std::cout << "LIVING ROOM----------------------------------------------------------" << std::endl;
              }
             
              else if ((lastpair.first == 'F' ) && (lastpair.second == 1)) {
                  std::cout << "FRONT HALL------------------------------------------------------------" << std::endl;
      
              } else {  //something not expected, unaligned read probably
                  std::cout << lastpair.first << " " << lastpair.second << std::endl;
                  serialFlush();
                  clear_d();
              }
                 
              } while (mqueue.size() > 0) ; 
              
              
              //AUDIO notification of last element of queue only  
              auto elapsed_time=std::chrono::duration_cast<std::chrono::seconds>(current_time - start_time).count();
               
              std::cout << "AUDIO ANNOUNCEMENT----------------------------------------------------------------------- " << std::endl;
              if (lastpair.first  ==  'D')
                   system("/usr/bin/mplayer samples/Dining_Room.mp3 >/dev/null 2>&1");  
                  //dining_room.play();
              else if (lastpair.first  ==  'E')
                   system("/usr/bin/mplayer samples/Living_Room.mp3 >/dev/null 2>&1");
                  //living_room.play();
              else if (lastpair.first  ==  'F')
                    system("/usr/bin/mplayer samples/Front_Hallway.mp3 >/dev/null 2>&1");
                  //front_hallway.play();
              start_time = std::chrono::high_resolution_clock::now();
     
      }
    }
    
    //EXITED the loop, restore the signal handler to OS default
    if (sigaction(SIGIO, &oldsa, NULL) < 0) {
		perror ("sigaction");
		return 1;
    }
      
    serialFlush();
    Disconnect();
    
    ao_close(dev);
    mpg123_exit();
    ao_shutdown();
    
    return 0;
}

Topic archived. No new replies allowed.