OS: Angstrom Linux 2012.12, kernel 3.8.13 running on a BeagleBone Black Rev A5B.
SDL: libsdl 1.2.0, sdl-config 1.2.15
I'm trying to write a tone generator on a BeagleBone Black using SDL. However, SDL audio doesn't seem to work unless I use the dummy driver. I'm using the following code to try to diagnose the SDL_AudioOpen issue:
#include <SDL/SDL.h>
#include <SDL/SDL_audio.h>
#include <iostream>
void audio_callback (void*, Uint8*, int) { }
void ReportError (const char *where, int status) {
std::cerr << "SDL Error: " << where << " (" << status << ") "
<< SDL_GetError () << std::endl;
exit (1);
}
void ReportEnv (const char *var) {
const char *driver = getenv (var);
if (NULL == driver)
std::cerr << var << " is null" << std::endl;
else
std::cerr << var << ": " << driver << std::endl;
}
int main (int argc, char **argv)
{ ReportEnv ("SDL_AUDIODRIVER");
int ret = SDL_Init (SDL_INIT_AUDIO);
if (0 != ret)
ReportError ("SDL_Init", ret);
SDL_AudioSpec ds, obtained;
ds . freq = 44100;
ds . format = AUDIO_S16;
ds . channels = 1;
ds . samples = 1024;
ds . callback = audio_callback;
ds . userdata = NULL;
ret = SDL_OpenAudio (&ds, &obtained);
if (0 != ret)
ReportError ("SDL_OpenAudio", ret);
std::cout << "Success" << std::endl;
return 0;
}
and I get the following results:
% SDL_AUDIODRIVER=dummy ./simple
SDL_AUDIODRIVER: dummy
Success
% SDL_AUDIODRIVER=alsa ./simple
SDL_AUDIODRIVER: alsa
SDL Error: SDL_OpenAudio (-1) No available audio device
% SDL_AUDIODRIVER=disk ./simple
SDL_AUDIODRIVER: disk
SDL Error: SDL_OpenAudio (-1) No available audio device
%
aplay works, so it seems that ALSA is at least partially configured correctly.
What am I missing? Seems like the disk driver should work under all circumstances.
Related
The question says it all. I am going in circles here. I set snd_pcm_sw_params_set_stop_threshold to boundary (and zero too just for fun) and I am still getting buffer underrun errors on snd_pcm_writei. I cannot understand why. The documentation is pretty clear on this:
If the stop threshold is equal to boundary (also software parameter - sw_param) then automatic stop will be disabled
Here is a minimally reproducible example:
#include <alsa/asoundlib.h>
#include <iostream>
#define AUDIO_DEV "default"
#define AC_FRAME_SIZE 960
#define AC_SAMPLE_RATE 48000
#define AC_CHANNELS 2
//BUILD g++ -o main main.cpp -lasound
using namespace std;
int main() {
int err;
unsigned int i;
snd_pcm_t *handle;
snd_pcm_sframes_t frames;
snd_pcm_uframes_t boundary;
snd_pcm_sw_params_t *sw;
snd_pcm_hw_params_t *params;
unsigned int s_rate;
unsigned int buffer_time;
snd_pcm_uframes_t f_size;
unsigned char buffer[AC_FRAME_SIZE * 2];
int rc;
for (i = 0; i < sizeof(buffer); i++)
buffer[i] = random() & 0xff;
if ((err = snd_pcm_open(&handle, AUDIO_DEV, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
cout << "open error " << snd_strerror(err) << endl;
return 0;
}
s_rate = AC_SAMPLE_RATE;
f_size = AC_FRAME_SIZE;
buffer_time = 2500;
cout << s_rate << " " << f_size << endl;
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(handle, params);
snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(handle, params, AC_CHANNELS);
snd_pcm_hw_params_set_rate_near(handle, params, &s_rate, 0);
snd_pcm_hw_params_set_period_size_near(handle, params, &f_size, 0);
cout << s_rate << " " << f_size << endl;
rc = snd_pcm_hw_params(handle, params);
if (rc < 0) {
cout << "open error " << snd_strerror(err) << endl;
return 0;
}
snd_pcm_sw_params_alloca(&sw);
snd_pcm_sw_params_current(handle, sw);
snd_pcm_sw_params_get_boundary(sw, &boundary);
snd_pcm_sw_params_set_stop_threshold(handle, sw, boundary);
rc = snd_pcm_sw_params(handle, sw);
if (rc < 0) {
cout << "open error " << snd_strerror(err) << endl;
return 0;
}
snd_pcm_sw_params_current(handle, sw);
snd_pcm_sw_params_get_stop_threshold(sw, &boundary);
cout << "VALUE " << boundary << endl;
for (i = 0; i < 1600; i++) {
usleep(100 * 1000);
frames = snd_pcm_writei(handle, buffer, f_size);
if (frames < 0)
frames = snd_pcm_recover(handle, frames, 0);
if (frames < 0) {
cout << "open error " << snd_strerror(frames) << endl;
break;
}
}
return 0;
}
Okay I figured it out. To anyone who runs into this issue who also has pipewire or pulse (or any other thirdparty non-alsa audio card) enabled as the "default" card the solution is to not use pipewire or pulse directly. It seems that snd_pcm_sw_params_set_stop_threshold is not implemented properly in pipewire/pulseaudio. You'll notice that if you disable pipewire or pulse this code will run exactly the way you want it to run.
Here is how you can disable pulseaudio (which was the issue on my system):
systemctl --user stop pulseaudio.socket
systemctl --user stop pulseaudio.service
Although a much better solution is to just set the AUDIO_DEV to write directly to an alsa card. You can find the names of these cards by running aplay -L. But in 95% of cases updating AUDIO_DEV in my sample code to the following:
#define AUDIO_DEV "hw:0,0"
Will usually fix the issue.
I am creating a background music player and I wanted to use the MPV C Plugin to do so, but my problem arrives when I disable displaying the video (with check_error(mpv_set_option_string(ctx, "vid", "no"));, this does the job of disabling the video, but then I can't use keys (like q (quit) or > (skip)) anymore... How do I allow them to be used in the terminal without the video GUI?
My Code:
#include <iostream>
#include <mpv/client.h>
static inline void check_error(int status)
{
if (status < 0)
{
std::cout << "mpv API error: " << mpv_error_string(status) << std::endl;
exit(1);
}
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
std::cout << "pass a single media file as argument" << std::endl;
return 1;
}
mpv_handle *ctx = mpv_create();
if (!ctx)
{
std::cout << "failed creating context" << std::endl;
return 1;
}
check_error(mpv_set_option_string(ctx, "input-default-bindings", "yes"));
mpv_set_option_string(ctx, "input-vo-keyboard", "yes");
int val = 1;
check_error(mpv_set_option(ctx, "osc", MPV_FORMAT_FLAG, &val));
check_error(mpv_initialize(ctx));
const char *cmd[] = {"loadfile", argv[1], NULL};
check_error(mpv_command(ctx, cmd));
// THIS IS WHAT I USE TO DISABLE THE VIDEO
// check_error(mpv_set_option_string(ctx, "vid", "no"));
// Let it play, and wait until the user quits.
while (1)
{
mpv_event *event = mpv_wait_event(ctx, 10000);
std::cout << "event: " << mpv_event_name(event->event_id) << std::endl;
if (event->event_id == MPV_EVENT_SHUTDOWN)
break;
}
mpv_terminate_destroy(ctx);
return 0;
}
As you can see with mpv_set_option_string(ctx, "input-default-bindings", "yes") I allow it to use keybinding, but how do I make the keybinding works with just the terminal, since it only works when the GUI is visible? If you ran: mpv path/to/video.mp3 --no-video then the key bindings would still work fine, even without the video GUI.
This is the first time I am implementing ssh programmatically and I am baffled about why my code does not work -- to be more specific, ssh_channel_read() keeps returning 0 bytes read. I don't know what I am doing wrong! I have been following the API instructions step by step but I am obviously omitting something inadvertently.
I am trying to connect to my Pi with a user name + password. Here is the complete code, you can just copy paste this and compile it with:
g++ main.cpp -lssh -o myapp
After the code, you can see the output I am getting. Please don't be harsh, like I said, this is the first time I am dealing with SSH:
#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv)
{
int vbs = SSH_LOG_RARE;
int timeout_ms = 1000;
ssh_session session = ssh_new();
ssh_channel channel;
char buffer[256];
int bytes_red;
if (session == NULL)
{
std::cout << "Failed to create ssh session." << std::endl;
exit(-1);
}
ssh_set_blocking(session, 1);
std::cout << "Created SSH session..." << std::endl;
ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
ssh_options_set(session, SSH_OPTIONS_USER, "pi#192.168.1.5");
ssh_options_set(session,SSH_OPTIONS_LOG_VERBOSITY, &vbs);
int con_result = ssh_connect(session);
int auth_result = ssh_userauth_password(session, "pi", "1234");
std::cout << "Connecton Result is: " << con_result << std::endl;
std::cout << "Auth Result is: " << auth_result << std::endl;
///////////////////////////////////////////
// Did we create the session successfully?
///////////////////////////////////////////
if (con_result != SSH_OK)
{
std::cout << "SSH connection failed. Error code is: " << con_result << std::endl;
ssh_free(session);
return con_result;
}
///////////////////////////////////////////
// Did we authenticate?
///////////////////////////////////////////
if (auth_result != SSH_AUTH_SUCCESS)
{
std::cout << "SSH authentication failed. Error code is: " << auth_result << std::endl;
ssh_free(session);
return auth_result;
}
///////////////////////////////////////////
// Create a new ssh_channel
///////////////////////////////////////////
channel = ssh_channel_new(session);
if (channel == NULL)
{
std::cout << "Failed to create SSH channel." << std::endl;
ssh_free(session);
return SSH_ERROR;
}
if (ssh_channel_is_open(channel))
std::cout << "Channel is open" << std::endl;
else
std::cout << "Channel is closed" << std::endl;
while(!ssh_channel_is_eof(channel))
{
bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);
// if (bytes_red)
std::cout << "Bytes read: " << bytes_red << std::endl;
}
std::cout << "Exiting ..." << std::endl;
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_free(session);
return 0;
}
and here is the output I am getting when running it:
$./myapp
Created SSH session...
[2018/05/19 14:57:14.246759, 1] socket_callback_connected: Socket connection callback: 1 (0)
[2018/05/19 14:57:14.301270, 1] ssh_client_connection_callback: SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301321, 1] ssh_analyze_banner: Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 14:57:14.301337, 1] ssh_analyze_banner: We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
Channel is closed
[2018/05/19 14:57:14.669298, 1] ssh_packet_process: Couldn't do anything with packet type 80
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
Bytes read: 0
^C
$
I can see the error, "Channel is closed" but why? What am I doing wrong?
After this, I also want to send data to the server and obviously get the feedback. From what I have read, ssh_channel_write() is the function to use.
I haven't dealt with SSH programmatically before and I am learning this as I write this.
All your help is very much appreciated.
Update
Thank to Jarra, I have solved this! Here is the final code that works!
#include <iostream>
#include <string>
#include <libssh/libsshpp.hpp>
int main(int argc, const char **argv)
{
int vbs = SSH_LOG_RARE;
int timeout_ms = 1000;
ssh_session session = ssh_new();
ssh_channel channel;
char buffer[256];
int bytes_red;
if (session == NULL)
{
std::cout << "Failed to create ssh session." << std::endl;
exit(-1);
}
ssh_set_blocking(session, 1);
std::cout << "Created SSH session..." << std::endl;
ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_PORT_STR, "22");
ssh_options_set(session, SSH_OPTIONS_USER, "pi#192.168.1.5");
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &vbs);
int con_result = ssh_connect(session);
int auth_result = ssh_userauth_password(session, "pi", "1234");
std::cout << "Connecton Result is: " << con_result << std::endl;
std::cout << "Auth Result is: " << auth_result << std::endl;
///////////////////////////////////////////
// Did we create the session successfully?
///////////////////////////////////////////
if (con_result != SSH_OK)
{
std::cout << "SSH connection failed. Error code is: " << con_result << std::endl;
ssh_free(session);
return con_result;
}
///////////////////////////////////////////
// Did we authenticate?
///////////////////////////////////////////
if (auth_result != SSH_AUTH_SUCCESS)
{
std::cout << "SSH authentication failed. Error code is: " << auth_result << std::endl;
ssh_free(session);
return auth_result;
}
///////////////////////////////////////////
// Create a new ssh_channel
///////////////////////////////////////////
channel = ssh_channel_new(session);
if (channel == NULL)
{
std::cout << "Failed to create SSH channel." << std::endl;
ssh_free(session);
return SSH_ERROR;
}
ssh_channel_open_session(channel);
if (ssh_channel_is_open(channel))
std::cout << "Channel is open" << std::endl;
else
std::cout << "Channel is closed" << std::endl;
int rc = ssh_channel_request_exec(channel, "ls");
while(!ssh_channel_is_eof(channel))
{
bytes_red = ssh_channel_read_timeout(channel, buffer, sizeof(buffer), 0, timeout_ms);
// if (bytes_red)
// std::cout << "Bytes read: " << bytes_red << std::endl;
std::cout << buffer << std::endl;
}
std::cout << "Exiting ..." << std::endl;
ssh_channel_close(channel);
ssh_channel_free(channel);
ssh_free(session);
return 0;
}
To compile: g++ main.cpp -lssh -o myapp and here is what you get when I run it:
./myapp
Created SSH session...
[2018/05/19 16:01:41.830861, 1] socket_callback_connected: Socket connection callback: 1 (0)
[2018/05/19 16:01:41.884875, 1] ssh_client_connection_callback: SSH server banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884929, 1] ssh_analyze_banner: Analyzing banner: SSH-2.0-OpenSSH_7.4p1 Raspbian-10+deb9u1
[2018/05/19 16:01:41.884945, 1] ssh_analyze_banner: We are talking to an OpenSSH client version: 7.4 (70400)
Connecton Result is: 0
Auth Result is: 0
[2018/05/19 16:01:42.258668, 1] ssh_packet_process: Couldn't do anything with packet type 80
Channel is open
Desktop
Documents
Downloads
Music
Pictures
Public
python_games
Templates
Videos
����s
Exiting ...
I just need to work on that last bit with the funny chars. This is straight out of my source code editor when I just got it to work, so the code isn't perfect.
ssh_channel_new allocated the resources for a new channel. It does not open it.
Depending on what you are trying to achieve you should then call an appropriate ssh_channel_open_XXXX function on that channel.
A simple example can be found here: https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/exec.c
First ssh_channel_open_session is called to open a session (shell) channel, and then ssh_channel_request_exec is called to execute the lsof command.
How/when you will write to the channel depends on the type of channel you have opened. An example of writing to a session channel (after calling cat > /dev/null on the host to pipe written data to /dev/null) can be seen here: https://github.com/substack/libssh/blob/c073979235eb0d0587ac9cb3c192e91e32d34b06/examples/senddata.c
I read and tried all the other posts to that topic, but nothing helped. When I try to play music with Mix_PlayChannel() I don't get an error nor do I hear some sound! I tried for hours now and nothing helps. The program just finishes happily. But no sound! I am using Ubuntu 12.04 64bit.
Thanks!
[EDIT]
Here is the code I use:
#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
int main(int argc, char** argv) {
Mix_Music *music = NULL;
Mix_Chunk *wave = NULL;
SDL_Init(SDL_INIT_AUDIO);
int audio_rate = 44100;
Uint16 audio_format = AUDIO_S16; /* 16-bit stereo */
int audio_channels = 1;
int audio_buffers = 4096;
if(Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers) < 0) {
printf("Unable to open audio!\n");
exit(1);
}
if(Mix_Init(MIX_INIT_MOD) != MIX_INIT_MOD)
std::cout << "errer";
Mix_Volume(-1, MIX_MAX_VOLUME);
music = Mix_LoadMUS("1.wav");
wave = Mix_LoadWAV("1.wav");
if (music == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
if (wave == NULL) {
std::cout << "Could not load 1.wav\n";
std::cout << Mix_GetError();
}
Mix_VolumeChunk(wave, MIX_MAX_VOLUME);
Mix_VolumeMusic(MIX_MAX_VOLUME);
Mix_PlayMusic(music, 0);
std::cout << Mix_GetError();
Mix_FadeInChannelTimed(-1, wave, 0, 100,1);
std::cout << Mix_GetError();
return 1;
}
I try both PlayMusic() and Mix_FadeInChannelTimed(). Both files are loaded correctly but not played. Sound is not muted, wav-file is playable with aplay or other tools. I check with alsamixer that all channels are open and not too low.
I now found out that the program needs to run until the sound has finished playing! I added a usleep() command after the play command and it plays nicely. So that was really mentioned nowhere that PlayMusic() does not keep running.
To create a opencl application the fist step is to get platforms by using
clGetPlatformIDs
I have a problem with the platforms that return from function ;the function return that i have 2 platforms but when i check them i found that i have one platform but it's duplicated !!
source code
struct PLATFORM
{
cl_platform_id _Platforms ;
map <cl_platform_info , char*> _Platforms_info ;
};
cl_int error ;
cl_uint temp_num_platforms ;
error = clGetPlatformIDs (NULL , NULL , &temp_num_platforms );
if ( error != CL_SUCCESS )
{
/* create error and debug function*/
cout << " error detect platforms " << endl << endl ;
}
else
{
cout << " we detect " << temp_num_platforms << " platforms " << endl << endl ;
_Platforms = std::unique_ptr < PLATFORM [] > ( new PLATFORM [temp_num_platforms] ) ;
for ( unsigned int num_platforms = 1 ; num_platforms <= temp_num_platforms ; num_platforms++ )
{
// get platforms
error = clGetPlatformIDs (num_platforms ,&_Platforms[num_platforms-1]._Platforms , NULL );
if ( error != CL_SUCCESS || _Platforms[num_platforms-1]._Platforms == NULL )
{
cout << " error get platform " << num_platforms - 1 << endl << endl;
}
else
{
cout << " OK ! we detect "<< num_platforms << " platform " << endl << endl ;
}
}
}
if ( _Platforms[0]._Platforms == _Platforms[1]._Platforms )
{
cout << " we have two platforms" << endl << endl ;
}
You haven't said much about your installation platform. My guess is that you have installed multiple versions of the OpenCL SDK from some vendor. That, or you've hit a bug. Try the program below, which prints out the vendor, name, and version of all the platforms reported on your system. It might help you understand your problem better.
// You might need to change this header based on your install:
#include <OpenCL/cl.h>
#include <stdio.h>
#include <stdlib.h>
static void check_error(cl_int error, char* name) {
if (error != CL_SUCCESS) {
fprintf(stderr, "Non-successful return code %d for %s. Exiting.\n", error, name);
exit(1);
}
}
int main (int argc, char const *argv[])
{
cl_uint i;
cl_int err;
// Discover the number of platforms:
cl_uint nplatforms;
err = clGetPlatformIDs(0, NULL, &nplatforms);
check_error(err, "clGetPlatformIds");
// Now ask OpenCL for the platform IDs:
cl_platform_id* platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * nplatforms);
err = clGetPlatformIDs(nplatforms, platforms, NULL);
check_error(err, "clGetPlatformIds");
// Ask OpenCL about each platform to understand the problem:
char name[128];
char vendor[128];
char version[128];
fprintf(stdout, "OpenCL reports %d platforms.\n\n", nplatforms);
for (i = 0; i < nplatforms; i++) {
err |= clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, 128, vendor, NULL);
err |= clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 128, name, NULL);
err |= clGetPlatformInfo(platforms[i], CL_PLATFORM_VERSION, 128, version, NULL);
check_error(err, "clGetPlatformInfo");
fprintf(stdout, "Platform %d: %s %s %s\n", i, vendor, name, version);
}
free(platforms);
return 0;
}
If you see two identical vendor-name-versions strings, then it's a bug. File it with your OpenCL vendor, and they'll thank you!