00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <pthread.h>
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <math.h>
00027 #include <float.h>
00028 #include <string.h>
00029 #include <limits.h>
00030 #include <unistd.h>
00031 #include <signal.h>
00032 #include <fcntl.h>
00033 #include <sched.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <gtk/gtk.h>
00037
00038 #include "BeamAudioUI.hh"
00039
00040
00041 G_LOCK_DEFINE_STATIC(gmInputMutex);
00042
00043 clBeamAudioUI *BeamAudioUI;
00044
00045
00046 int main (int argc, char *argv[])
00047 {
00048 int iRetVal = 0;
00049
00050 signal(SIGPIPE, SIG_IGN);
00051 signal(SIGFPE, SIG_IGN);
00052 BeamAudioUI = new clBeamAudioUI(&argc, &argv);
00053 iRetVal = BeamAudioUI->Main();
00054 delete BeamAudioUI;
00055 return iRetVal;
00056 }
00057
00058
00059 gboolean WrapOnDelete (GtkWidget *gwSender, GdkEvent *geEvent, gpointer gpData)
00060 {
00061 return BeamAudioUI->OnDelete(gwSender, geEvent, gpData);
00062 }
00063
00064
00065 void WrapOnConnectClick (GtkButton *gbButton, gpointer gpData)
00066 {
00067 BeamAudioUI->OnConnectClick(gbButton, gpData);
00068 }
00069
00070
00071 void WrapOnValueChanged (GtkAdjustment *gaAdjustment, gpointer gpData)
00072 {
00073 BeamAudioUI->OnValueChanged(gaAdjustment, gpData);
00074 }
00075
00076
00077 void WrapOnToggled (GtkToggleButton *gtbToggleButton, gpointer gpData)
00078 {
00079 BeamAudioUI->OnToggled(gtbToggleButton, gpData);
00080 }
00081
00082
00083 void WrapOnGdkInput (gpointer gpData, gint giSource,
00084 GdkInputCondition gicCondition)
00085 {
00086 BeamAudioUI->OnGdkInput(gpData, giSource, gicCondition);
00087 }
00088
00089
00090 void *WrapAudioOutThread (void *vpParam)
00091 {
00092 return BeamAudioUI->AudioOutThread(vpParam);
00093 }
00094
00095
00096 void clBeamAudioUI::Build ()
00097 {
00098
00099 gwWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00100 gtk_window_set_title(GTK_WINDOW(gwWindow), cpWindowTxt);
00101
00102 gtk_window_set_policy(GTK_WINDOW(gwWindow), TRUE, TRUE, FALSE);
00103
00104
00105
00106 gwVBox = gtk_vbox_new(FALSE, BAUI_PADDING);
00107 gtk_container_add(GTK_CONTAINER(gwWindow), gwVBox);
00108 gtk_widget_show(gwVBox);
00109
00110
00111 BuildTable1();
00112
00113
00114 BuildTable2();
00115
00116
00117 gwLDirection = gtk_label_new(cpLDirectionTxt);
00118 gtk_label_set_justify(GTK_LABEL(gwLDirection), GTK_JUSTIFY_LEFT);
00119 gtk_box_pack_start(GTK_BOX(gwVBox), gwLDirection, TRUE, FALSE, 0);
00120 gtk_widget_show(gwLDirection);
00121 goADirection = gtk_adjustment_new(0.0,
00122 -(BAUI_DEF_DIR_RANGE / 2.0), BAUI_DEF_DIR_RANGE / 2.0,
00123 1.0, 10.0, 1.0);
00124 gwHSDirection = gtk_hscale_new(GTK_ADJUSTMENT(goADirection));
00125 gtk_scale_set_draw_value(GTK_SCALE(gwHSDirection), TRUE);
00126 gtk_box_pack_start(GTK_BOX(gwVBox), gwHSDirection, TRUE, FALSE, 0);
00127 gtk_widget_show(gwHSDirection);
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 gwStatusBar = gtk_statusbar_new();
00144 gtk_box_pack_start(GTK_BOX(gwVBox), gwStatusBar, FALSE, FALSE, 0);
00145 gtk_widget_show(gwStatusBar);
00146 guSbCtxt = gtk_statusbar_get_context_id(GTK_STATUSBAR(gwStatusBar),
00147 "status");
00148 gtk_statusbar_push(GTK_STATUSBAR(gwStatusBar), guSbCtxt, "");
00149
00150
00151 gtk_widget_show(gwWindow);
00152
00153 ConnectSignals();
00154 }
00155
00156
00157 void clBeamAudioUI::BuildTable1 ()
00158 {
00159
00160 gwTable1 = gtk_table_new(2, 2, FALSE);
00161
00162 gtk_box_pack_start(GTK_BOX(gwVBox), gwTable1, TRUE, FALSE, 0);
00163 gtk_widget_show(gwTable1);
00164
00165
00166 gwLServer = gtk_label_new(cpLServerTxt);
00167 gtk_label_set_justify(GTK_LABEL(gwLServer), GTK_JUSTIFY_LEFT);
00168 gtk_table_attach(GTK_TABLE(gwTable1), gwLServer,
00169 0, 1, 0, 1,
00170 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00171 (GtkAttachOptions) 0,
00172 BAUI_PADDING / 2, 0);
00173 gtk_widget_show(gwLServer);
00174 gwCServer = gtk_combo_new();
00175 gtk_entry_set_max_length(GTK_ENTRY(GTK_COMBO(gwCServer)->entry),
00176 BAUI_SERVER_MAXLEN);
00177 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(gwCServer)->entry),
00178 "127.0.0.1:30001");
00179
00180
00181 gtk_table_attach(GTK_TABLE(gwTable1), gwCServer,
00182 0, 1, 1, 2,
00183 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00184 (GtkAttachOptions) 0,
00185 BAUI_PADDING / 2, 0);
00186 gtk_widget_show(gwCServer);
00187 GtkUtils.ComboListFromFile(gwCServer, &glServer, BAUI_HOSTFILE);
00188
00189
00190 gwBConnect = gtk_button_new_with_label(cpBConnectTxt);
00191 gtk_table_attach(GTK_TABLE(gwTable1), gwBConnect,
00192 1, 2, 1, 2,
00193 (GtkAttachOptions) GTK_FILL, (GtkAttachOptions) 0,
00194 BAUI_PADDING / 2, 0);
00195 gtk_widget_show(gwBConnect);
00196 }
00197
00198
00199 void clBeamAudioUI::BuildTable2 ()
00200 {
00201
00202 gwTable2 = gtk_table_new(2, 3, FALSE);
00203
00204 gtk_box_pack_start(GTK_BOX(gwVBox), gwTable2, TRUE, FALSE, 0);
00205 gtk_widget_show(gwTable2);
00206
00207
00208 gwLSoundSpeed = gtk_label_new(cpLSoundSpeedTxt);
00209 gtk_label_set_justify(GTK_LABEL(gwLSoundSpeed), GTK_JUSTIFY_LEFT);
00210 gtk_table_attach(GTK_TABLE(gwTable2), gwLSoundSpeed,
00211 0, 1, 0, 1,
00212 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00213 (GtkAttachOptions) 0,
00214 BAUI_PADDING / 2, 0);
00215 gtk_widget_show(gwLSoundSpeed);
00216 gwESoundSpeed = gtk_entry_new();
00217 gtk_table_attach(GTK_TABLE(gwTable2), gwESoundSpeed,
00218 0, 1, 1, 2,
00219 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND|GTK_SHRINK),
00220 (GtkAttachOptions) 0,
00221 BAUI_PADDING / 2, 0);
00222 gtk_widget_show(gwESoundSpeed);
00223 gtk_entry_set_text(GTK_ENTRY(gwESoundSpeed), BAUI_DEF_SOUNDSPEED);
00224
00225
00226 gwCBHighFreq = gtk_check_button_new_with_label(cpCBHighFreqTxt);
00227 gtk_table_attach(GTK_TABLE(gwTable2), gwCBHighFreq,
00228 1, 2, 0, 1,
00229 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
00230 (GtkAttachOptions) 0,
00231 BAUI_PADDING / 2, 0);
00232 gtk_widget_show(gwCBHighFreq);
00233
00234
00235 gwCBDither = gtk_check_button_new_with_label(cpCBDitherTxt);
00236 gtk_table_attach(GTK_TABLE(gwTable2), gwCBDither,
00237 1, 2, 1, 2,
00238 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
00239 (GtkAttachOptions) 0,
00240 BAUI_PADDING / 2, 0);
00241 gtk_widget_show(gwCBDither);
00242
00243
00244 gwCB3DAudio = gtk_check_button_new_with_label(cpCB3DAudioTxt);
00245 gtk_table_attach(GTK_TABLE(gwTable2), gwCB3DAudio,
00246 2, 3, 0, 1,
00247 (GtkAttachOptions) (GTK_FILL|GTK_EXPAND),
00248 (GtkAttachOptions) 0,
00249 BAUI_PADDING / 2, 0);
00250 gtk_widget_show(gwCB3DAudio);
00251 }
00252
00253
00254 void clBeamAudioUI::ConnectSignals ()
00255 {
00256 gtk_signal_connect(GTK_OBJECT(gwWindow), "delete-event",
00257 GTK_SIGNAL_FUNC(WrapOnDelete), NULL);
00258
00259 gtk_signal_connect(GTK_OBJECT(gwBConnect), "clicked",
00260 GTK_SIGNAL_FUNC(WrapOnConnectClick), NULL);
00261
00262 gtk_signal_connect(goADirection, "value-changed",
00263 GTK_SIGNAL_FUNC(WrapOnValueChanged), NULL);
00264
00265
00266
00267
00268 gtk_signal_connect(GTK_OBJECT(gwCBHighFreq), "toggled",
00269 GTK_SIGNAL_FUNC(WrapOnToggled), NULL);
00270
00271 gtk_signal_connect(GTK_OBJECT(gwCBDither), "toggled",
00272 GTK_SIGNAL_FUNC(WrapOnToggled), NULL);
00273
00274 gtk_signal_connect(GTK_OBJECT(gwCB3DAudio), "toggled",
00275 GTK_SIGNAL_FUNC(WrapOnToggled), NULL);
00276 }
00277
00278
00279 bool clBeamAudioUI::ParseServerStr (char *cpHostAddr, int *ipHostPort,
00280 const char *cpSourceStr)
00281 {
00282 char cpTempStr[BAUI_SERVER_MAXLEN + 1];
00283 char *cpTempHost;
00284 char *cpTempPort;
00285
00286 strncpy(cpTempStr, cpSourceStr, BAUI_SERVER_MAXLEN);
00287 cpTempHost = strtok(cpTempStr, ": \t\n");
00288 if (cpTempHost != NULL)
00289 {
00290 strcpy(cpHostAddr, cpTempHost);
00291 cpTempPort = strtok(NULL, " \t\n");
00292 if (cpTempPort != NULL)
00293 {
00294 *ipHostPort = atoi(cpTempPort);
00295 if (*ipHostPort > 0) return true;
00296 }
00297 }
00298 return false;
00299 }
00300
00301
00302 bool clBeamAudioUI::InitConnection (const char *cpHostAddr, int iHostPort)
00303 {
00304 int iSockH;
00305 char cpReqProcName[GLOBAL_HEADER_LEN];
00306
00307 iSockH = SClient.Connect(cpHostAddr, NULL, iHostPort);
00308 if (iSockH < 0)
00309 {
00310 g_print("Failed to connect host!\n");
00311 return false;
00312 }
00313 g_print("Connection established - sending process request...\n");
00314 bConnected = true;
00315 SOp.SetHandle(iSockH);
00316 strcpy(cpReqProcName, BAUI_REQ_PROC);
00317 if (SOp.WriteN(cpReqProcName, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00318 {
00319 g_print("Failed to send process request!\n");
00320 return false;
00321 }
00322 g_print("Sending settings...\n");
00323 if (!SendSettings())
00324 {
00325 g_print("Failed to send settings!\n");
00326 return false;
00327 }
00328 lClips = 0l;
00329 giGdkTag = gdk_input_add(iSockH, GDK_INPUT_READ, WrapOnGdkInput, NULL);
00330 return true;
00331 }
00332
00333
00334 bool clBeamAudioUI::SendSettings ()
00335 {
00336 char cpMsgBuf[GLOBAL_HEADER_LEN];
00337 stBeamAudioFirst sFirst;
00338
00339 sRequest.fDirection = GTK_ADJUSTMENT(goADirection)->value;
00340 sscanf(gtk_entry_get_text(GTK_ENTRY(gwESoundSpeed)), "%f",
00341 &sRequest.fSoundSpeed);
00342 sRequest.bHighFreq =
00343 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gwCBHighFreq))) ?
00344 true : false;
00345 Msg.SetRequest(cpMsgBuf, &sRequest);
00346 if (SOp.WriteN(cpMsgBuf, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00347 return false;
00348 if (!SOp.ReadSelect(BAUI_1ST_TIMEOUT))
00349 return false;
00350 if (SOp.ReadN(cpMsgBuf, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00351 return false;
00352 Msg.GetFirst(cpMsgBuf, &sFirst);
00353 AllocateBuffers(&sFirst);
00354 lBufIdx = 0l;
00355 pthread_create(&ptidAudio, NULL, WrapAudioOutThread, NULL);
00356 return true;
00357 }
00358
00359
00360 void clBeamAudioUI::AllocateBuffers (const stpBeamAudioFirst spFirst)
00361 {
00362 long lBufCntr;
00363 long lSampleCntr;
00364 char *cpDitherRand;
00365
00366 iSampleRate = spFirst->iSampleRate;
00367 lFragSize = spFirst->lBufLength;
00368 lDataCount = lFragSize * 2;
00369 lMsgSize = GLOBAL_HEADER_LEN + lFragSize * sizeof(GDT);
00370 MessageBuf.Size(lMsgSize);
00371 InAudioBuf.Size(lFragSize * sizeof(GDT));
00372 fpInAudio = InAudioBuf;
00373 SrcAudioBuf.Size(lDataCount * sizeof(GDT));
00374 fpSrcAudio = SrcAudioBuf;
00375 DitherBuf.Size(lDataCount * sizeof(BAUI_INT_DATATYPE));
00376 DitherRandBuf.Size(lFragSize * sizeof(char));
00377 for (lBufCntr = 0l; lBufCntr < BAUI_AUDIO_BUFCOUNT; lBufCntr++)
00378 {
00379 OutAudioBuf[lBufCntr].Size(
00380 lDataCount * sizeof(BAUI_SND_DATATYPE));
00381 ipOutAudio[lBufCntr] = OutAudioBuf[lBufCntr];
00382 memset(ipOutAudio[lBufCntr], 0x00,
00383 spFirst->lBufLength * sizeof(BAUI_SND_DATATYPE));
00384 }
00385 Audio3D.Initialize(lFragSize);
00386 g_print("Incoming fragment size %li (%.3f ms)\n",
00387 lFragSize, (float) lFragSize / (float) iSampleRate * 1000.0f);
00388 g_print("Buffering %i fragments (%.3f ms)\n",
00389 BAUI_AUDIO_BUFCOUNT,
00390 (float) lFragSize / (float) iSampleRate * 1000.0f *
00391 BAUI_AUDIO_BUFCOUNT);
00392
00393 cpDitherRand = DitherRandBuf;
00394 if (iRandH >= 0)
00395 {
00396 if (read(iRandH, cpDitherRand, lFragSize) < lFragSize)
00397 {
00398 g_print("Read from /dev/urandom failed!?\n");
00399 }
00400 }
00401 else
00402 {
00403 for (lSampleCntr = 0; lSampleCntr < lFragSize; lSampleCntr++)
00404 {
00405 cpDitherRand[lSampleCntr] = (char) (random() & 0xff);
00406 }
00407 }
00408 }
00409
00410
00411 #if (!defined(BSDSYS) && !defined(__QNX__))
00412 #ifdef USE_ALSA05
00413 bool clBeamAudioUI::InitAudio (clAudio &Audio, clAudioA &AudioA)
00414 #else
00415 bool clBeamAudioUI::InitAudio (clAudio &Audio, clAudioA2 &AudioA)
00416 #endif
00417 #elif defined(BSDSYS)
00418 bool clBeamAudioUI::InitAudio (clAudio &Audio)
00419 #elif defined(__QNX__)
00420 bool clBeamAudioUI::InitAudio (clAudioA &AudioA)
00421 #endif
00422 {
00423 int iAudioSR = iSampleRate;
00424 int iAudioCh = 2;
00425
00426 if (!bALSA)
00427 {
00428 #ifndef __QNX__
00429 int iAudioFormat = BAUI_SND_FORMAT;
00430 char cpDevice[_POSIX_PATH_MAX + 1];
00431
00432 if (!Cfg.GetStr("AudioDevice", cpDevice))
00433 strcpy(cpDevice, "/dev/dsp");
00434 g_print("Open device %s fs %i ch %i fmt %xh\n", cpDevice, iAudioSR,
00435 iAudioCh, iAudioFormat);
00436 Audio.Open(cpDevice, &iAudioFormat, &iAudioSR, &iAudioCh,
00437 AUDIO_WRITE);
00438 g_print("Device opened fs %i ch %i fmt %xh\n",
00439 iAudioSR, iAudioCh, iAudioFormat);
00440 #else
00441 g_warning("OSS not supported under QNX");
00442 #endif
00443 }
00444 else
00445 {
00446 #ifndef BSDSYS
00447 int iALSACard;
00448 int iALSADevice;
00449 int iALSASubDevice;
00450 int iAudioBits = BAUI_SND_BITS;
00451 #ifndef USE_ALSA05
00452 char cpDeviceId[10];
00453 #endif
00454
00455 if (!Cfg.GetInt("ALSACard", &iALSACard))
00456 iALSACard = 0;
00457 if (!Cfg.GetInt("ALSADevice", &iALSADevice))
00458 iALSADevice = 0;
00459 if (!Cfg.GetInt("ALSASubDevice", &iALSASubDevice))
00460 iALSASubDevice = 0;
00461 g_print("Open device %i:%i:%i fs %i ch %i wl %i\n",
00462 iALSACard, iALSADevice, iALSASubDevice,
00463 iAudioSR, iAudioCh, iAudioBits);
00464 if (!AudioA.CardOpen(iALSACard))
00465 {
00466 g_print("ALSA card open failed!\n");
00467 return false;
00468 }
00469 #ifdef USE_ALSA05
00470 if (!AudioA.PcmOpen(iALSADevice, iALSASubDevice, AA_MODE_PLAY))
00471 #else
00472 sprintf(cpDeviceId, "plughw:%i,%i", iALSACard, iALSADevice);
00473 if (!AudioA.PcmOpen(cpDeviceId, AA_MODE_PLAY))
00474 #endif
00475 {
00476 g_print("ALSA PCM device open failed!\n");
00477 return false;
00478 }
00479 #ifdef USE_ALSA05
00480 if (!AudioA.PcmSetSetup(iAudioCh, iAudioSR, iAudioBits,
00481 lFragSize * sizeof(BAUI_SND_DATATYPE), false))
00482 #else
00483 if (!AudioA.PcmSetSetup(iAudioCh, iAudioSR, iAudioBits,
00484 lFragSize * sizeof(BAUI_SND_DATATYPE), 2))
00485 #endif
00486 {
00487 g_print("ALSA PCM setup failed!\n");
00488 return false;
00489 }
00490 g_print("Device opened fs %i ch %i wl %i frag %i bytes\n",
00491 AudioA.PcmGetSampleRate(),
00492 AudioA.PcmGetChannels(),
00493 AudioA.PcmGetBits(),
00494 AudioA.PcmGetFragmentSize());
00495 if (!AudioA.PcmPrepare())
00496 {
00497 g_print("ALSA PCM prepare failed!\n");
00498 return false;
00499 }
00500 #else
00501 g_warning("ALSA not supported under BSD systems");
00502 #endif
00503 }
00504 return true;
00505 }
00506
00507
00508 void clBeamAudioUI::UpdateSettings ()
00509 {
00510 char cpMsgBuf[GLOBAL_HEADER_LEN];
00511
00512 if (bConnected)
00513 {
00514 Msg.SetRequest(cpMsgBuf, &sRequest);
00515 if (SOp.WriteSelect(0))
00516 {
00517 if (SOp.WriteN(cpMsgBuf, GLOBAL_HEADER_LEN) < GLOBAL_HEADER_LEN)
00518 {
00519 g_print("SockOp::WriteN() error: %s\n",
00520 strerror(SOp.GetErrno()));
00521 }
00522 }
00523 else
00524 {
00525 g_print("Server busy...\n");
00526 }
00527 }
00528 }
00529
00530
00531 void clBeamAudioUI::ConvertMS ()
00532 {
00533 long lSrcCntr;
00534 long lDestCntr;
00535
00536 lDestCntr = 0;
00537 for (lSrcCntr = 0; lSrcCntr < lFragSize; lSrcCntr++)
00538 {
00539 fpSrcAudio[lDestCntr++] = fpInAudio[lSrcCntr];
00540 fpSrcAudio[lDestCntr++] = fpInAudio[lSrcCntr];
00541 }
00542 }
00543
00544
00545 void clBeamAudioUI::Process3D ()
00546 {
00547 long lBlockSize;
00548 long lBlockCount;
00549 long lBlockCntr;
00550
00551 lBlockSize = Audio3D.GetWindowSize();
00552 lBlockCount = lFragSize / lBlockSize;
00553 for (lBlockCntr = 0; lBlockCntr < lBlockCount; lBlockCntr++)
00554 {
00555 Audio3D.Process(&fpSrcAudio[lBlockCntr * lBlockSize * 2]);
00556 }
00557 }
00558
00559
00560 void clBeamAudioUI::Dither ()
00561 {
00562 long lDithCntr;
00563 long lSampleCntr;
00564 BAUI_INT_DATATYPE *ipDither;
00565 char *cpDitherRand;
00566
00567 ipDither = DitherBuf;
00568 cpDitherRand = DitherRandBuf;
00569 lSampleCntr = 0;
00570 for (lDithCntr = 0; lDithCntr < lFragSize; lDithCntr++)
00571 {
00572 ipDither[lSampleCntr] =
00573 DSP.Round(fpSrcAudio[lSampleCntr] * 0x007fff00);
00574 ipDither[lSampleCntr] += cpDitherRand[lDithCntr];
00575 lSampleCntr++;
00576 ipDither[lSampleCntr] =
00577 DSP.Round(fpSrcAudio[lSampleCntr] * 0x007fff00);
00578 ipDither[lSampleCntr] += cpDitherRand[lDithCntr];
00579 lSampleCntr++;
00580 }
00581 }
00582
00583
00584 void clBeamAudioUI::ConvertFromDither ()
00585 {
00586 long lSampleCntr;
00587 BAUI_INT_DATATYPE *ipConvSrc;
00588 BAUI_SND_DATATYPE *ipConvDest;
00589
00590 ipConvSrc = DitherBuf;
00591 ipConvDest = ipOutAudio[lBufIdx];
00592 for (lSampleCntr = 0; lSampleCntr < lDataCount; lSampleCntr++)
00593 {
00594 ipConvDest[lSampleCntr] = (BAUI_SND_DATATYPE)
00595 (ipConvSrc[lSampleCntr] >> 8);
00596 }
00597 }
00598
00599
00600 clBeamAudioUI::clBeamAudioUI (int *ipArgCount, char ***cpapArgVect)
00601 {
00602 int iALSA;
00603
00604 bConnected = false;
00605 bDither = false;
00606 b3DAudio = false;
00607 bALSA = false;
00608 iPrevHeading = 0;
00609
00610 g_print("BeamAudio UI v%i.%i.%i\n", BAUI_VER_MAJ, BAUI_VER_MIN,
00611 BAUI_VER_PL);
00612 g_print("Copyright (C) 2000-2001 Jussi Laako\n\n");
00613
00614 g_print("Gtk+ version %i.%i.%i\n", gtk_major_version, gtk_minor_version,
00615 gtk_micro_version);
00616 g_print("Locale set to %s\n\n", gtk_set_locale());
00617 gtk_init(ipArgCount, cpapArgVect);
00618
00619 Cfg.SetFileName(BAUI_CFGFILE);
00620 if (Cfg.GetInt("UseALSA", &iALSA))
00621 {
00622 bALSA = (iALSA) ? true : false;
00623 }
00624 else bALSA = false;
00625
00626 Build();
00627
00628 iRandH = open("/dev/urandom", O_RDONLY);
00629 if (iRandH < 0)
00630 {
00631 g_print("Unable to open /dev/urandom for reading, using random()\n");
00632 }
00633 }
00634
00635
00636 clBeamAudioUI::~clBeamAudioUI ()
00637 {
00638 if (iRandH >= 0) close(iRandH);
00639 }
00640
00641
00642 int clBeamAudioUI::Main ()
00643 {
00644 gtk_main();
00645 return 0;
00646 }
00647
00648
00649 gboolean clBeamAudioUI::OnDelete (GtkWidget *gwSender, GdkEvent *geEvent,
00650 gpointer gpData)
00651 {
00652 if (bConnected) gdk_input_remove(giGdkTag);
00653 gtk_main_quit();
00654 return TRUE;
00655 }
00656
00657
00658 void clBeamAudioUI::OnConnectClick (GtkButton *gbButton, gpointer gpData)
00659 {
00660 int iHostPort;
00661 char cpHostAddr[BAUI_SERVER_MAXLEN + 1];
00662
00663 if (ParseServerStr(cpHostAddr, &iHostPort,
00664 gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(gwCServer)->entry))))
00665 {
00666 g_print("Connecting to host %s port %i...\n", cpHostAddr, iHostPort);
00667 if (bConnected)
00668 {
00669 bConnected = false;
00670 gdk_input_remove(giGdkTag);
00671 SOp.Close();
00672 pthread_join(ptidAudio, NULL);
00673 }
00674 if (InitConnection(cpHostAddr, iHostPort))
00675 {
00676 g_print("OK\n\n");
00677 }
00678 else
00679 {
00680 g_print("Failed\n\n");
00681 }
00682 }
00683 else
00684 {
00685 g_print("Incorrect server entry! Format: <host>:<port>\n");
00686 }
00687 }
00688
00689
00690 void clBeamAudioUI::OnValueChanged (GtkAdjustment *gaAdjustment,
00691 gpointer gpData)
00692 {
00693 if (gaAdjustment == GTK_ADJUSTMENT(goADirection))
00694 {
00695 sRequest.fDirection = DSP.DegToRad(gaAdjustment->value);
00696 UpdateSettings();
00697 }
00698
00699
00700
00701
00702 }
00703
00704
00705 void clBeamAudioUI::OnToggled (GtkToggleButton *gtbToggleButton,
00706 gpointer gpData)
00707 {
00708 if (gtbToggleButton == GTK_TOGGLE_BUTTON(gwCBHighFreq))
00709 {
00710 sRequest.bHighFreq =
00711 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gwCBHighFreq))) ?
00712 true : false;
00713 UpdateSettings();
00714 }
00715 else if (gtbToggleButton == GTK_TOGGLE_BUTTON(gwCBDither))
00716 {
00717 bDither =
00718 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gwCBDither))) ?
00719 true : false;
00720 }
00721 else if (gtbToggleButton == GTK_TOGGLE_BUTTON(gwCB3DAudio))
00722 {
00723 b3DAudio =
00724 (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(gwCB3DAudio))) ?
00725 true : false;
00726 }
00727 }
00728
00729
00730 void clBeamAudioUI::OnGdkInput (gpointer gpData, gint giSource,
00731 GdkInputCondition gicCondition)
00732 {
00733 int iHeading;
00734 char cpStatusTxt[BAUI_CONV_BUF_LEN + 1];
00735 stBeamAudioRes sResHdr;
00736
00737 if (!bConnected) return;
00738 G_LOCK(gmInputMutex);
00739 if (SOp.ReadSelect(0))
00740 {
00741 if (SOp.ReadN(MessageBuf, lMsgSize) == lMsgSize)
00742 {
00743 Msg.GetResult(MessageBuf, &sResHdr, fpInAudio);
00744 ConvertMS();
00745 iHeading = DSP.Round(DSP.RadToDeg(sResHdr.fDirection));
00746 if (iPrevHeading != iHeading)
00747 {
00748
00749
00750 Audio3D.SetAngles(iHeading, 0, 0);
00751 iPrevHeading = iHeading;
00752 }
00753 if (b3DAudio) Process3D();
00754 if (bDither) Dither();
00755 OutBufMutex[lBufIdx].Wait();
00756 if (!bDither)
00757 {
00758 DSP.Convert(ipOutAudio[lBufIdx], fpSrcAudio, lDataCount,
00759 false);
00760 }
00761 else
00762 {
00763 ConvertFromDither();
00764 }
00765 OutBufMutex[lBufIdx].Release();
00766 lBufIdx++;
00767 if (lBufIdx >= BAUI_AUDIO_BUFCOUNT) lBufIdx = 0l;
00768 if (sResHdr.fPeakLevel == 0.0f) lClips++;
00769 g_snprintf(cpStatusTxt, BAUI_CONV_BUF_LEN,
00770 "%.1f deg %.1f dB %li clips",
00771 DSP.RadToDeg(sResHdr.fDirection), sResHdr.fPeakLevel, lClips);
00772 gtk_statusbar_pop(GTK_STATUSBAR(gwStatusBar), guSbCtxt);
00773 gtk_statusbar_push(GTK_STATUSBAR(gwStatusBar), guSbCtxt,
00774 cpStatusTxt);
00775 }
00776 else
00777 {
00778 g_print("Receive error: %s\n", strerror(SOp.GetErrno()));
00779 }
00780 }
00781 G_UNLOCK(gmInputMutex);
00782 }
00783
00784
00785 void *clBeamAudioUI::AudioOutThread (void *vpParam)
00786 {
00787 long lOutIdx = 0l;
00788 long lOutBufSize = lDataCount * sizeof(BAUI_SND_DATATYPE);
00789 #ifndef __QNX__
00790 struct audio_buf_info sAudioBufInfo;
00791 #endif
00792 clAlloc ZeroBuf;
00793 #ifndef __QNX__
00794 clAudio Audio;
00795 #endif
00796 #ifndef BSDSYS
00797 #ifdef USE_ALSA05
00798 clAudioA AudioA;
00799 #else
00800 clAudioA2 AudioA;
00801 #endif
00802 #endif
00803
00804 ZeroBuf.Size(lOutBufSize);
00805 memset(ZeroBuf, 0x00, lOutBufSize);
00806 #if (!defined(BSDSYS) && !defined(__QNX__))
00807 InitAudio(Audio, AudioA);
00808 #elif defined(BSDSYS)
00809 InitAudio(Audio);
00810 #elif defined(__QNX__)
00811 InitAudio(AudioA);
00812 #endif
00813 while (lBufIdx < (BAUI_AUDIO_BUFCOUNT / 2) && bConnected) sched_yield();
00814 if (!bALSA)
00815 {
00816 #ifndef __QNX__
00817 do
00818 {
00819 Audio.Write(ZeroBuf, lOutBufSize);
00820 Audio.GetOutBufInfo(&sAudioBufInfo);
00821 } while (sAudioBufInfo.bytes > lOutBufSize && bConnected);
00822 #endif
00823 }
00824 else
00825 {
00826 #ifndef BSDSYS
00827 #ifdef USE_ALSA05
00828 AudioA.PcmGo();
00829 #else
00830 AudioA.PcmStart();
00831 #endif
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 #endif
00843 }
00844 while (bConnected)
00845 {
00846 OutBufMutex[lOutIdx].Wait();
00847 if (!bALSA)
00848 {
00849 #ifndef __QNX__
00850 if (Audio.Write(ipOutAudio[lOutIdx], lOutBufSize) < lOutBufSize)
00851 g_warning("Error writing to PCM device");
00852 #endif
00853 }
00854 else
00855 {
00856 #ifndef BSDSYS
00857 int iErrorCode;
00858
00859 iErrorCode = AudioA.PcmWrite(ipOutAudio[lOutIdx], lOutBufSize);
00860 if (iErrorCode < 0)
00861 {
00862
00863
00864 }
00865 #endif
00866 }
00867 OutBufMutex[lOutIdx].Release();
00868 lOutIdx++;
00869 if (lOutIdx >= BAUI_AUDIO_BUFCOUNT) lOutIdx = 0l;
00870 }
00871 if (!bALSA)
00872 {
00873 #ifndef __QNX__
00874 Audio.Close();
00875 #endif
00876 }
00877 else
00878 {
00879 #ifndef BSDSYS
00880 AudioA.PcmClose();
00881 AudioA.CardClose();
00882 #endif
00883 }
00884 return NULL;
00885 }
00886