RS232 input/output help needed
Hi, I'm new at programming and new at Linux. It happened so, that I'm working on a project where i thought I'd just edit already written program and have the wished result. Well what do you know! It isn't as easy as I assumed :) I've got a code of an internet radio tuner, but I want to make it send output (status1, status2 and status3 text in code) character by character (1 second interval between characters) to my serial RS232 port. And I need the program to react (change preset) to input from RS232 serial port. So when I connect my serial LCD and keypad to computer RS232 i get external user interface for the program. In my mind it sounded way easier than it seems to be to me. The OS is Ubuntu. I've got this code:
Code:
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <glib/gthread.h>
#include <stdlib.h>
#include <string.h>
#include "bass.h"
// path to glade file
#ifndef GLADE_PATH
#define GLADE_PATH ""
#endif
GladeXML *glade;
GtkWidget *win=0;
GThread *cthread=0;
guint prebuftimer;
HSTREAM chan;
const char *urls[10]={ // preset stream URLs
"http://servers.internet-radio.org.uk/tools/playlistgenerator/?u=http://cp.internet-radio.org.uk:15634/listen.pls&t=.pls",
"http://84.32.194.146/crfm.aac.m3u",
"http://84.32.194.146:80/crfm.aac",
"http://somafm.com/tags.pls","http://somafm.com/tags32.pls",
"http://somafm.com/secretagent.pls","http://somafm.com/secretagent24.pls"
};
char proxy[100]=""; // proxy server
// display error messages
void Error(const char *es)
{
GtkWidget *dialog=gtk_message_dialog_new(GTK_WINDOW(win),GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,"%s\n(error code: %d)",es,BASS_ErrorGetCode());
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
#define GetWidget(id) glade_xml_get_widget(glade,id)
void WindowDestroy(GtkObject *obj, gpointer data)
{
gtk_main_quit();
}
void gtk_label_set_text_8859(GtkLabel *label, const gchar *text)
{
gsize s;
char *utf=g_convert(text,-1,"UTF-8","ISO-8859-1",NULL,&s,NULL);
if (utf) {
gtk_label_set_text(label,utf);
g_free(utf);
} else
gtk_label_set_text(label,text);
}
// update stream title from metadata
void DoMeta()
{
GtkLabel *label=GTK_LABEL(GetWidget("status1"));
const char *meta=BASS_ChannelGetTags(chan,BASS_TAG_META);
if (meta) { // got Shoutcast metadata
char *p=strstr(meta,"StreamTitle='");
if (p) {
p=strdup(p+13);
strchr(p,';')[-1]=0;
gtk_label_set_text_8859(label,p);
free(p);
}
} else {
meta=BASS_ChannelGetTags(chan,BASS_TAG_OGG);
if (meta) { // got Icecast/OGG tags
const char *artist=NULL,*title=NULL,*p=meta;
for (;*p;p+=strlen(p)+1) {
if (!strncasecmp(p,"artist=",7)) // found the artist
artist=p+7;
if (!strncasecmp(p,"title=",6)) // found the title
title=p+6;
}
if (artist) {
char text[100];
snprintf(text,sizeof(text),"%s - %s",artist,title);
gtk_label_set_text(label,text);
} else if (title)
gtk_label_set_text(label,title);
}
}
}
void CALLBACK MetaSync(HSYNC handle, DWORD channel, DWORD data, void *user)
{
gdk_threads_enter();
DoMeta();
gdk_threads_leave();
}
void CALLBACK EndSync(HSYNC handle, DWORD channel, DWORD data, void *user)
{
gdk_threads_enter();
gtk_label_set_text(GTK_LABEL(GetWidget("status1")),"");
gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"not playing");
gtk_label_set_text(GTK_LABEL(GetWidget("status3")),"");
gdk_threads_leave();
}
void CALLBACK StatusProc(const void *buffer, DWORD length, void *user)
{
if (buffer && !length) {
gdk_threads_enter();
gtk_label_set_text(GTK_LABEL(GetWidget("status3")),buffer); // display connection status
gdk_threads_leave();
}
}
gboolean PrebufTimerProc(gpointer data)
{ // monitor prebuffering progress
DWORD progress=BASS_StreamGetFilePosition(chan,BASS_FILEPOS_BUFFER)
*100/BASS_StreamGetFilePosition(chan,BASS_FILEPOS_END); // percentage of buffer filled
if (progress>75 || !BASS_StreamGetFilePosition(chan,BASS_FILEPOS_CONNECTED)) { // over 75% full (or end of download)
{ // get the broadcast name and URL
const char *icy=BASS_ChannelGetTags(chan,BASS_TAG_ICY);
if (!icy) icy=BASS_ChannelGetTags(chan,BASS_TAG_HTTP); // no ICY tags, try HTTP
if (icy) {
for (;*icy;icy+=strlen(icy)+1) {
if (!strncasecmp(icy,"icy-name:",9))
gtk_label_set_text_8859(GTK_LABEL(GetWidget("status2")),icy+9);
if (!strncasecmp(icy,"icy-url:",8))
gtk_label_set_text_8859(GTK_LABEL(GetWidget("status3")),icy+8);
}
} else
gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"");
}
// get the stream title and set sync for subsequent titles
DoMeta();
BASS_ChannelSetSync(chan,BASS_SYNC_META,0,&MetaSync,0); // Shoutcast
BASS_ChannelSetSync(chan,BASS_SYNC_OGG_CHANGE,0,&MetaSync,0); // Icecast/OGG
// set sync for end of stream
BASS_ChannelSetSync(chan,BASS_SYNC_END,0,&EndSync,0);
// play it!
BASS_ChannelPlay(chan,FALSE);
return FALSE; // stop monitoring
} else {
char text[20];
sprintf(text,"buffering... %d%%",progress);
gtk_label_set_text(GTK_LABEL(GetWidget("status2")),text);
return TRUE; // continue monitoring
}
}
void *OpenURL(char *url)
{
g_source_remove(prebuftimer); // stop prebuffer monitoring
BASS_StreamFree(chan); // close old stream
gdk_threads_enter();
gtk_label_set_text(GTK_LABEL(GetWidget("status1")),"");
gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"connecting...");
gtk_label_set_text(GTK_LABEL(GetWidget("status3")),"");
gdk_threads_leave();
if (!(chan=BASS_StreamCreateURL(url,0,BASS_SAMPLE_FLOAT|BASS_STREAM_STATUS|BASS_STREAM_AUTOFREE,StatusProc,0))) {
gdk_threads_enter();
gtk_label_set_text(GTK_LABEL(GetWidget("status2")),"not playing");
Error("Can't play the stream");
gdk_threads_leave();
} else
prebuftimer=g_timeout_add(50,PrebufTimerProc,NULL); // start prebuffer monitoring
cthread=0;
return NULL;
}
void PresetClicked(GtkButton *obj, gpointer data)
{
if (cthread) { // already connecting
// beep!
} else {
const char *url;
const gchar *objname=gtk_widget_get_name(GTK_WIDGET(obj));
if (!strcmp(objname,"customopen")) { // play a custom URL
url=gtk_entry_get_text(GTK_ENTRY(GetWidget("customurl")));
} else { // play a preset
int preset=atoi(objname+6)-1; // get preset from button name ("presetX")
url=urls[preset];
}
strcpy(proxy,gtk_entry_get_text(GTK_ENTRY(GetWidget("proxyurl")))); // get proxy server
// open URL in a new thread (so that main thread is free)
cthread=g_thread_create(OpenURL,url,FALSE,NULL);
}
}
void ProxyDirectToggled(GtkToggleButton *obj, gpointer data)
{
if (obj->active)
BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,NULL); // disable proxy
else
BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); // enable proxy
}
int main(int argc, char* argv[])
{
g_thread_init(NULL);
gdk_threads_init();
gtk_init(&argc,&argv);
// check the correct BASS was loaded
if (HIWORD(BASS_GetVersion())!=BASSVERSION) {
Error("An incorrect version of BASS was loaded");
return 0;
}
// initialize default output device
if (!BASS_Init(-1,44100,0,NULL,NULL)) {
Error("Can't initialize device");
return 0;
}
BASS_SetConfig(BASS_CONFIG_NET_PLAYLIST,1); // enable playlist processing
BASS_SetConfig(BASS_CONFIG_NET_PREBUF,0); // minimize automatic pre-buffering, so we can do it (and display it) instead
BASS_SetConfigPtr(BASS_CONFIG_NET_PROXY,proxy); // setup proxy server location
// initialize GUI
glade=glade_xml_new(GLADE_PATH"netradio.glade",NULL,NULL);
if (!glade) return 0;
win=GetWidget("window1");
if (!win) return 0;
glade_xml_signal_autoconnect(glade);
gdk_threads_enter();
gtk_main();
gdk_threads_leave();
BASS_Free();
return 0;
}
I know I should add some function like this to open serial port:
Code:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
/*
* 'open_port()' - Open serial port 1.
*
* Returns the file descriptor on success or -1 on error.
*/
int main;
open_port(void)
{
int fd; /* File descriptor for the port */
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
/*
* Could not open the port.
*/
perror("open_port: Unable to open /dev/ttyS0 - ");
}
else
fcntl(fd, F_SETFL, 0);
return (fd);
}
Plus something more to write to serial port and read from it. I found something about kbhit command, but it seems to be on some special library that's got something complicated about it. I guess it would be too much to expect somebody to give me the edited version of the code, but any information, links, hints or wisdom sharing will be appreciated.