Streaming audio file in C on linux - c

I have a .au audio file and am reading it in parts using fread. However when i write this to /dev/audio there is no sound being played. Do I need to do something or is the system supposed to play back as soon as I write to /dev/audio. I am not getting any errors.
player = open("/dev/audio", O_WRONLY, 0);
if (player < 0)
{
perror("Opening /dev/audio failed\n");
exit(1);
}
while(1)
{
//code to read from the file writes to buf 1000 bytes per read
//fread(buf,1000, 1, audioFile); //server side
write(player, buf, 1000);
}

The issue seems to be with Ubuntu. I tried the same on a Gentoo installation in my lab and the sound can be heard

Related

Linux on RPi debian, hidraw write() to USB device outputs a few junk characters to /dev/hidraw0 which if not cleared jam the device

We have a set of USB devices which we monitor using a RPi. The monitoring code polls the devices using hidraw direct interface about once a second. The protocol uses 64 byte packets to send commands and receive data and all responses are 64 bytes long at most.
The same scheme works fine under Windows using the Windows HID driver. On Linux however we use hidraw and find that the device interface gets jammed after a short time resulting in unsuccessful write{}s to the device.
After a lot of investigation I came across a recommendation to try to follow the communication between a host and an hidraw device using this in a terminal:
sudo cat /dev/hidraw0
As it turns out, running this command outputs 4-8 bytes of unreadable characters to the terminal every write() and unexpectedly it also clears the jam for hidraw0. All subsequent write()'s and read()'s to that device work flawlessly.
If that device is disconnected and then reconnected the jam condition returns shortly thereafter. I have single stepped the code and verified that the "junk" is output during the execution of the write().
I tried to add fsync() calls before and after the write() in hope to clear the buffers and avoid this issue but that did not help. The code for the write() and subsequent read() is standard as follows:
#define USB_PACKET 64
#define USB_WRDELAY 10 //ms
FILE* fd;
int errno, res;
char packet[USB_PACKET];
fd = 0;
/* Open the Device with non-blocking reads. */
fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK);
if (fd < 0) {
perror("Unable to open device");
return 0; // failure
}
memset(packet, 0x0, sizeof(packet));
packet[0] = 0x34; // command code - request for USB device status bytes
fsync();
res = write(fd, &packet, sizeof(packet));
fsync();
if (res < 0) {
printf("Error: %d in USB write()\n", errno);
close(fd);
return 0; // failure
} else {
usleep(1000*USB_WRDELAY ); // delay gives OS and device time to respond
res = read(fd, &packet, sizeof(packet));
if (res < 0) {
printf("Error: %d in USB read()\n", errno);
close(fd);
return 0; // failure
} else {
// good read, packet holds the response data
// process the device data
close(fd);
return 1; // OK
}
}
return 0; // failure
This is a sample of the gibberish we read on the terminal running the cat command for each executed write():
4n��#/5 �
I am not understanding where this junk comes from and how to get rid of it. I tried several things that did not work out such as adding a read() with a timeout before the write - hoping it is some data left from a previous incomplete read().
Also tried to write a smaller buffer as I need only send only a 2 byte command as well as adding a delay between the open() and write().
Unfortunately using the cat in the terminal interferes with the hot plug/unplug detection of the USB devices so it is not a solution we can use in deployment.
I'll appreciate any words of wisdom on this.

fopen/fdopen freezes on broken network shares or removed usb devices

I am building a background service for a embedded linux device in C.
Every hour a file is read either from a network share or a usb device,
but if the network or usb device was plugged out, fopen never returns
and the service freezes. I am not allowed to use async methods like pthread or fork to read that file, so i am looking for a solution with a timeout or something non-blocking to test if the file (or device) is available.
The code examples below are freezing on fopen/fdopen.
FILE* f = fopen("/path/to/file", "r"); //freezes if device not available;
if(f)
{
< .. read file .. >
fclose(f);
}
////////////////////////////////////////////
FILE* f = NULL;
int fd = open("/path/to/file", O_RDONLY|O_NONBLOCK);
if(fd>=0)
{
f= fdopen(fd, "r");//freezes if device not available
}
if(f)
{
< .. read file .. >
fclose(f);
}
else
{
if(fd>=0){close(fd);}
}
edit:
the answers for fopen does not return do not solve my issue. i do know why this is happening, but the service must not wait for a unresponsive device. as described above, i need a non blocking solution or a timeout.

Client does not read any data after reading another file

I am writing a simple client/server application and I ran into a very weird issue.
I am trying to send a .zip file to the client and some more data after that.
Sending the .zip works fine, the server writes to the socket, the client reads from the socket, just as intended.
The problem is right after that.
The server runs fine and keeps writing to the socket, but the client just won't read anything. It gets stuck on the very next read() call, no matter what I try to send.
I've checked to see if the socket descriptors are alright, and they are. I also thought that maybe there is not enough data in the socket for the client to read, but there definitely is.
I also tried doing the same write/read before and after sending that .zip file: it works fine before, but client doesn't see it after sending that .zip.
I am out of ideas.
Here's the function I use to send the .zip:
typedef struct thData{
int idThread; //thread ID
int cl; //client descriptor
}thData;
void send_info(struct thData tdL)
{
char file_path[256]="v1.zip";
char sd_buffer[256];
bzero(sd_buffer, 256);
FILE *fd = fopen(file_path, "rb");
if(fd == NULL)
{
printf("ERROR: %s not found.\n", file_path);
exit(1);
}
int read_size;
int write_size;
while((read_size = fread(sd_buffer, sizeof(char), 256, fd)) > 0)
{
if((write_size=write(tdL.cl, sd_buffer, read_size)) < 0)
{
perror("ERROR: writing to client: \n");
break;
}
bzero(sd_buffer, 256);
}
}
And what I use to receive the .zip:
void receive_info(int sd) //sd being the socket descriptor
{
char* file_path = "subject.zip";
char received_buffer[256];
int total_received=0;
int total_wrote=0;
FILE *fd = fopen(file_path, "wb");
if(fd == NULL)
printf("Cannot open %s\n", file_path);
else
{
bzero(received_buffer, 256);
int read_size = 0;
while((read_size = read(sd, received_buffer, 256)) > 0)
{
total_received=total_received+read_size;
int write_size = fwrite(received_buffer, sizeof(char), read_size, fd);
total_wrote=total_wrote+read_size;
if(write_size < read_size)
{
perror("ERROR: \n");
}
bzero(received_buffer, 256);
if (read_size == 0 || read_size != 256)
{
break;
}
}
if(read_size < 0)
{
perror("ERROR: reading: ");
exit(1);
}
fclose(fd);
}
}
Any help would be greatly appreciated.
I think that the problem is that you are reading too much.
In TCP there are no boundaries in the packets sent from one peer to the other. It is just a stream of bytes, and the pieces received from recv/read() bear no relation (in principle) to the pieces sent from send/write().
Now, imagine that your ZIP file is 300 bytes long, and your extra data is 10 bytes long. Your sender code will do:
write 256 bytes (first piece from ZIP).
write 44 bytes (last piece from ZIP).
write 10 bytes (the extra data).
And your receiver code will do:
read 256, get 256 bytes (first piece from ZIP).
read 256, get 54 bytes (last piece from ZIP plus the extra data).
read XXX bytes, wait forever!
If you look carefully to the ZIP files you'll probably see those extra bytes at the end of subject.zip.
The solution, if you don't want to close and open another socket, is to make the protocol a bit more complicated. For example, you could send a structure before the file (a header) that includes the size of the file. That way the receiver will know when to stop reading.
PS: Note that your code has a few risky edges. For example, write() might not write all the given bytes, but you are not checking that; you are not closing the file...
PS2: I find curious that you feel the need to write sizeof(char) instead of just 1 but you write 256 instead of sizeof(sd_buffer).

Streaming engines best practice in C

LANG: C / ENV: Linux
I am developing a streaming engine, for now I am able to start, stop and pause the stream, but seeking is the operation that's giving me a lot of headache, I already asked a question here before and fixed some issues inside the code from the answers.
Using lseek() function, I am passing the open streaming file descriptor as first argument, plus I am using UDP for transmitting, something like the following code:
transport_fd = open(tsfile, O_RDONLY);
int offset = 1024;
off_t offsetIndicator;
if ((offsetIndicator=lseek(transport_fd, offset, SEEK_CUR))<0) printf("Error seeking\n");
Whenever I try to seek while streaming, the streaming stops and the pictures hangs.
Is there anything I should pay attention to?, i.e: like attempting to sleep() or nanosleep() after seeking into the file in order for the changes to take effect.
I couldn't find examples, papers or realted articles for best practices in such engines.
EDIT:
After testing, it seems like the file continued to stream but receiving devices on the network didn't catch the stream connection anymore, and calculating the time it took to finish after subtract seeking time, the stream seems to be finished normally.
CODE SNIPPET:
while (!completed)
{
while (/* Comparing conditions */ && !completed)
{
if (seekLck == 1) // seekLck is a semaphore to test seek signal from father process initiated by 0
{
int offset = 1024;
off_t offsetIndicator;
if ((offsetIndicator=lseek(transport_fd, offset, SEEK_CUR))<0)
printf("Error seeking\n");
nanosleep(&nano_sleep_packet, 0); //Try to sleep to see if it is still hanging, didn't work
seekLck = 0;
}
len = read(transport_fd, send_buf, packet_size);
if(len < 0) {
fprintf(stderr, "File read error \n");
completed = 1;
}
else if (len == 0)
{
fprintf(stderr, "Sent done\n");
completed = 1;
}
else
{
sent = sendto(sockfdstr, send_buf, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if(sent <= 0)
{
perror("send(): error ");
completed = 1;
}
}
}
nanosleep(&nano_sleep_packet, 0);
}
close(transport_fd);
close(sockfdstr);
free(send_buf);
printf("cleaning up\n");
return 0;
}
The main question was "Why isn't the file being streamed (Played) even when lseek() is working fine?"...
Actually nothing was wrong from the server side, but even though, the clients weren't able to continue streaming after losing the frame count (streaming ffmpeg frames, clients are getting the stream from a video scrambler).
What worked for me in this situation is getting the socket parameter and killing (in a clean way) the process that needs to be seeked in while holding the stream position, after that start a totally new stream from the seek position with the same socket parameter so it replaces the old one.
I hope this will help someone out there especially that there's no much documentation about those stuff.

Serial communication buffer data out of order

I'm trying to implement a simple SLAM project with Arduino and C on Linux Mint 15.
The Arduino project is sending data to notebook via bluetooth (serial). The data is read by a C program. In Arduino serial, the data is shown correctly, but in the notebook, the received data is wrong. (In image, white is Arduino data. The terminal shows the 'received' data.)
I'm sending d080x096y099z035 (for example) and receiving 99z0356y0999z035 (out of order?).
So, I have some questions:
What can I do to make the read()command in C, read the data in the correct order and length? (order: d000x000y000z000, length = 16)
In the Arduino sending function, are there length differences using Serial.print(char buffer[]) and Serial.println(char buffer[])? (Like adding a '\n' or something else at the end of buffer?)
Should I use the delay() function in the Arduino code or in the C code?
In Arduino:
...
int buffer_size = 17;
char buffer[17];
//void setup()
void loop(){
//create the string resp = "d000x111y222z333"
...
resp.toCharArray(buffer, buffersize);
bluetooth.print(buffer);
delay(200);
}
In C program:
...
int fd = open("/dev/rfcomm4", O_RDONLY | O_NOCTTY | O_NDELAY);
printf("fd code %d\n", fd);
if (fd == -1)
{
gchar *msg = "open_port: Unable to open /dev/rfcomm4";
gtk_label_set_text(GTK_LABEL(label), msg);
perror("error: ");
}
char buffer[17];
int n;
printf("entering in loop...\n");
while (1)
{
n = read(fd, buffer, sizeof(buffer));
printf("%s\n", buffer);
}
Sorry I'm not an expert but just a few ideas you might check concering your questions:
to 1) I guess it might be a problem with encoding, as Python AFAIK expects files to be unicode. So try open (.... ,encoding='ascii') or whatever encoding you use
Please also pay attention that you might block the GTK mainthread, that causes heavy delays in your UI. So I recommend creating a own thread for reading the serial port and filling an internal buffer, that get's rendered by the GTK mainthread, if you send an update request:
http://www.pardon-sleeuwaegen.be/antoon/python/page0.html

Resources