Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

BeamAudioUI.cc

Go to the documentation of this file.
00001 /*
00002 
00003     User interface for beam audio server
00004     Copyright (C) 2000-2001 Jussi Laako
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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     // - Main window
00099     gwWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00100     gtk_window_set_title(GTK_WINDOW(gwWindow), cpWindowTxt);
00101     // shrink, grow, auto-shrink
00102     gtk_window_set_policy(GTK_WINDOW(gwWindow), TRUE, TRUE, FALSE);
00103 
00104     // - VerticalBox
00105     // homogenous, spacing
00106     gwVBox = gtk_vbox_new(FALSE, BAUI_PADDING);
00107     gtk_container_add(GTK_CONTAINER(gwWindow), gwVBox);
00108     gtk_widget_show(gwVBox);
00109 
00110     // - Table 1
00111     BuildTable1();
00112 
00113     // - Table 2
00114     BuildTable2();
00115 
00116     // - Label & HorizontalScale: Direction
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     // - Label & HorizontabScale: Distance
00130     /*gwLDistance = gtk_label_new(cpLDistanceTxt);
00131     gtk_label_set_justify(GTK_LABEL(gwLDistance), GTK_JUSTIFY_LEFT);
00132     gtk_box_pack_start(GTK_BOX(gwVBox), gwLDistance, TRUE, FALSE, 0);
00133     gtk_widget_show(gwLDistance);
00134     // value, lower, upper, step_increment, page_increment, page_size
00135     goADistance = gtk_adjustment_new(0.0, 0.0, 1.0, 0.01, 0.01, 0.01);
00136     gwHSDistance = gtk_hscale_new(GTK_ADJUSTMENT(goADistance));
00137     gtk_scale_set_digits(GTK_SCALE(gwHSDistance), 2);
00138     gtk_scale_set_draw_value(GTK_SCALE(gwHSDistance), TRUE);
00139     gtk_box_pack_start(GTK_BOX(gwVBox), gwHSDistance, TRUE, FALSE, 0);
00140     gtk_widget_show(gwHSDistance);*/
00141 
00142     // - StatusBar
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     // Delayed realization of main window
00151     gtk_widget_show(gwWindow);
00152 
00153     ConnectSignals();
00154 }
00155 
00156 
00157 void clBeamAudioUI::BuildTable1 ()
00158 {
00159     // rows, columns, homogenous
00160     gwTable1 = gtk_table_new(2, 2, FALSE);
00161     // box, child, expand, fill, padding
00162     gtk_box_pack_start(GTK_BOX(gwVBox), gwTable1, TRUE, FALSE, 0);
00163     gtk_widget_show(gwTable1);
00164 
00165     // - Label & Combo: Server
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     // table, child, left attach, right attach, top attach, bottom attach,
00180     // x-options, y-options, x-padding, y-padding
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     // - Button: Connect
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     // rows, columns, homogenous
00202     gwTable2 = gtk_table_new(2, 3, FALSE);
00203     // box, child, expand, fill, padding
00204     gtk_box_pack_start(GTK_BOX(gwVBox), gwTable2, TRUE, FALSE, 0);
00205     gtk_widget_show(gwTable2);
00206 
00207     // - Label & Entry: Sound speed
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     // - CheckButton: High frequencies
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     // - CheckButton: Dither
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     // - CheckButton: 3D
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     /*gtk_signal_connect(goADistance, "value-changed",
00266         GTK_SIGNAL_FUNC(WrapOnValueChanged), NULL);*/
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     // Initialize random buffer for dither
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     /*else if (gaAdjustment == GTK_ADJUSTMENT(goADistance))
00699     {
00700         Audio3D.SetAngles(iPrevHeading, 0, gaAdjustment->value);
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                 /*Audio3D.SetAngles(iHeading, 0, 
00749                     GTK_ADJUSTMENT(goADistance)->value);*/
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         /*do
00833         {
00834             if (AudioA.PcmWrite(ZeroBuf, lOutBufSize) < lOutBufSize)
00835             {
00836                 //g_print("Error writing to PCM device\n");
00837                 break;
00838             }
00839         } while (AudioA.PcmGetBufFree() > lOutBufSize && bConnected);*/
00840         /*g_message("Status: %s", 
00841             AudioA.PcmGetStatusStr(AudioA.PcmGetStatus()));*/
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                 /*g_warning("Error writing to PCM device: %s",
00863                     snd_strerror(iErrorCode));*/
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 

Generated on Sun Oct 26 19:11:18 2003 for HASAS by doxygen 1.3.3