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 <unistd.h>
00027 #include <string.h>
00028 #include <math.h>
00029 #include <float.h>
00030 #include <signal.h>
00031 #include <errno.h>
00032 #include <sched.h>
00033 #include <sys/types.h>
00034 #include <sys/mman.h>
00035 #include <gtk/gtk.h>
00036
00037 #include "SoundUI.hh"
00038
00039
00040 static const char *cpWindowTxt = "Sound UI";
00041 static const char *cpChannelPfx = "Channel";
00042
00043 static const char *cpLServerTxt = "Server";
00044 static const char *cpLChannelTxt = "Channel";
00045 static const char *cpBConnectTxt = "Connect";
00046
00047 static const char *cpLInputLevelTxt = "Average peak input level";
00048 static const char *cpLEqTxt = "Eq";
00049
00050 static const char *cpLOutputLevelTxt = "Level";
00051 static const char *cpBApplyCurveTxt = "Apply curve";
00052
00053 clSoundUI *SoundUI;
00054
00055
00056 int main (int argc, char *argv[])
00057 {
00058 int iRetVal;
00059
00060 signal(SIGPIPE, SIG_IGN);
00061 signal(SIGFPE, SIG_IGN);
00062 SoundUI = new clSoundUI(&argc, &argv);
00063 iRetVal = SoundUI->Exec();
00064 delete SoundUI;
00065 return iRetVal;
00066 }
00067
00068
00069
00070
00071
00072 gboolean WrapOnDeleteEvent (GtkWidget *gwSender, GdkEvent *geEvent,
00073 gpointer gpData)
00074 {
00075 return SoundUI->OnDeleteEvent(gwSender, geEvent, gpData);
00076 }
00077
00078
00079 void WrapOnClickedEvent (GtkButton *gbButton, gpointer gpData)
00080 {
00081 SoundUI->OnClickedEvent(gbButton, gpData);
00082 }
00083
00084
00085 gint WrapOnTimeoutEvent (gpointer gpData)
00086 {
00087 return SoundUI->OnTimeoutEvent(gpData);
00088 }
00089
00090
00091 void WrapOnToggledEvent (GtkToggleButton *gtbToggleButton, gpointer gpData)
00092 {
00093 SoundUI->OnToggledEvent(gtbToggleButton, gpData);
00094 }
00095
00096
00097 void WrapOnValueChangedEvent (GtkAdjustment *gaAdjustment, gpointer gpData)
00098 {
00099 SoundUI->OnValueChangedEvent(gaAdjustment, gpData);
00100 }
00101
00102
00103 void WrapOnApplyCurveClicked (GtkButton *gbButton, gpointer gpData)
00104 {
00105 SoundUI->OnApplyCurveClicked(gbButton, gpData);
00106 }
00107
00108
00109 void WrapOnMotionCurve (GtkWidget *gwSender, GdkEventMotion *gemEvent,
00110 gpointer gpData)
00111 {
00112 SoundUI->OnMotionCurve(gwSender, gemEvent, gpData);
00113 }
00114
00115
00116 void *WrapSoundOutThread (void *vpData)
00117 {
00118 return SoundUI->SoundOutThread(vpData);
00119 }
00120
00121
00122 void *WrapSoundInThread (void *vpData)
00123 {
00124 return SoundUI->SoundInThread(vpData);
00125 }
00126
00127
00128
00129
00130
00131 void clSoundUI::GetCfg ()
00132 {
00133 int iALSA;
00134 int iLocalCh;
00135 int iLocalSR;
00136 long lLocalSC;
00137
00138 Cfg.SetFileName(SUI_CFGFILE);
00139 if (!Cfg.GetStr("Device", cpDevice))
00140 strcpy(cpDevice, SUI_DEF_DEVICE);
00141 if (!Cfg.GetInt("DeviceBase", &iDeviceBase))
00142 iDeviceBase = -1;
00143 if (Cfg.GetInt("UseALSA", &iALSA))
00144 {
00145 bALSA = (iALSA) ? true : false;
00146 }
00147 else bALSA = false;
00148 if (!Cfg.GetInt("ALSACard", &iALSACard))
00149 iALSACard = 0;
00150 if (!Cfg.GetInt("ALSADevice", &iALSADevice))
00151 iALSADevice = 0;
00152 if (!Cfg.GetInt("ALSASubDevice", &iALSASubDevice))
00153 iALSASubDevice = 0;
00154 if (Cfg.GetInt("Channels", &iLocalCh))
00155 iChCount = iLocalCh;
00156 else
00157 iChCount = SUI_DEF_CHANNELS;
00158 if (Cfg.GetInt("SampleRate", &iLocalSR))
00159 iSampleRate = iLocalSR;
00160 else
00161 iSampleRate = SUI_DEF_SAMPLERATE;
00162 if (Cfg.GetInt("SampleCount", &lLocalSC))
00163 lSampleCount = lLocalSC;
00164 else
00165 lSampleCount = SUI_SAMPLECOUNT;
00166 if (!Cfg.GetInt("UpdateInterval", &iVuTimeout))
00167 iVuTimeout = SUI_VU_TIMEOUT;
00168 if (!Cfg.GetInt("DCBlock", &iDCBlock))
00169 iDCBlock = 0;
00170 }
00171
00172
00173 void clSoundUI::BuildGUI ()
00174 {
00175 int iWidgetCntr;
00176 int iWidgetCount;
00177 int iLocalOctaves;
00178 long lSpectSize;
00179
00180 gwWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00181 gtk_window_set_title(GTK_WINDOW(gwWindow), cpWindowTxt);
00182
00183 gtk_window_set_policy(GTK_WINDOW(gwWindow), TRUE, TRUE, FALSE);
00184 gtk_container_set_border_width(GTK_CONTAINER(gwWindow), SUI_PADDING);
00185
00186
00187 gwVBox = gtk_vbox_new(FALSE, SUI_PADDING);
00188 gtk_container_add(GTK_CONTAINER(gwWindow), gwVBox);
00189 gtk_widget_show(gwVBox);
00190
00191
00192 gwHBox = gtk_hbox_new(TRUE, SUI_PADDING);
00193
00194 gtk_box_pack_start(GTK_BOX(gwVBox), gwHBox, TRUE, TRUE, 0);
00195 gtk_widget_show(gwHBox);
00196
00197 gwStatusbar = gtk_statusbar_new();
00198 gtk_box_pack_start(GTK_BOX(gwVBox), gwStatusbar, FALSE, FALSE, 0);
00199 guiStatusbarCtxt = gtk_statusbar_get_context_id(
00200 GTK_STATUSBAR(gwStatusbar), "status");
00201 gtk_statusbar_push(GTK_STATUSBAR(gwStatusbar), guiStatusbarCtxt, "");
00202 gtk_widget_show(gwStatusbar);
00203
00204 MutexData.Wait();
00205 iWidgetCount = iChCount;
00206 iLocalOctaves = iOctaveCount;
00207 lSpectSize = lSampleCount + 1L;
00208 MutexData.Release();
00209 for (iWidgetCntr = 0; iWidgetCntr < iWidgetCount; iWidgetCntr++)
00210 {
00211 SoundChGUI[iWidgetCntr] = new clSoundChGUI(gwHBox, iWidgetCntr + 1,
00212 iLocalOctaves, lSpectSize);
00213 }
00214
00215 ConnectSignals();
00216
00217
00218 gtk_widget_show(gwWindow);
00219 }
00220
00221
00222 void clSoundUI::ConnectSignals ()
00223 {
00224 int iWidgetCntr;
00225 int iWidgetCount;
00226 int iObjectCntr;
00227 int iObjectCount;
00228 int iObjectMask;
00229
00230 gtk_signal_connect(GTK_OBJECT(gwWindow), "delete-event",
00231 GTK_SIGNAL_FUNC(WrapOnDeleteEvent), NULL);
00232 MutexData.Wait();
00233 iWidgetCount = iChCount;
00234 iObjectCount = iOctaveCount;
00235 MutexData.Release();
00236 for (iWidgetCntr = 0; iWidgetCntr < iWidgetCount; iWidgetCntr++)
00237 {
00238 gtk_signal_connect(GTK_OBJECT(SoundChGUI[iWidgetCntr]->gwBConnect),
00239 "clicked", GTK_SIGNAL_FUNC(WrapOnClickedEvent),
00240 GINT_TO_POINTER(iWidgetCntr));
00241 gtk_signal_connect(GTK_OBJECT(SoundChGUI[iWidgetCntr]->gwCBEq),
00242 "toggled", GTK_SIGNAL_FUNC(WrapOnToggledEvent),
00243 GINT_TO_POINTER(iWidgetCntr));
00244 gtk_signal_connect(GTK_OBJECT(SoundChGUI[iWidgetCntr]->goAOutputLevel),
00245 "value-changed", GTK_SIGNAL_FUNC(WrapOnValueChangedEvent),
00246 GINT_TO_POINTER(iWidgetCntr << 16));
00247 for (iObjectCntr = 0; iObjectCntr < iObjectCount; iObjectCntr++)
00248 {
00249 iObjectMask = (iWidgetCntr << 16);
00250 iObjectMask |= ((iObjectCntr + 1) & 0xffff);
00251 gtk_signal_connect(
00252 GTK_OBJECT(SoundChGUI[iWidgetCntr]->goaAEqLevel[iObjectCntr]),
00253 "value-changed", GTK_SIGNAL_FUNC(WrapOnValueChangedEvent),
00254 GINT_TO_POINTER(iObjectMask));
00255 }
00256 gtk_signal_connect(GTK_OBJECT(SoundChGUI[iWidgetCntr]->gwBApplyCurve),
00257 "clicked", GTK_SIGNAL_FUNC(WrapOnApplyCurveClicked),
00258 GINT_TO_POINTER(iWidgetCntr));
00259 gtk_signal_connect(GTK_OBJECT(SoundChGUI[iWidgetCntr]->gwCurveEq),
00260 "motion_notify_event", GTK_SIGNAL_FUNC(WrapOnMotionCurve),
00261 GINT_TO_POINTER(iWidgetCntr));
00262 }
00263 }
00264
00265
00266 bool clSoundUI::ParseServerStr (char *cpHostRes, int *ipPortRes,
00267 const char *cpSourceStr)
00268 {
00269 char cpTempStr[SUI_SERV_MAXLEN + 1];
00270 char *cpTempHost;
00271 char *cpTempPort;
00272
00273 strncpy(cpTempStr, cpSourceStr, SUI_SERV_MAXLEN);
00274 cpTempHost = strtok(cpTempStr, ": \t\n");
00275 if (cpTempHost != NULL)
00276 {
00277 strcpy(cpHostRes, cpTempHost);
00278 cpTempPort = strtok(NULL, " \t\n");
00279 if (cpTempPort != NULL)
00280 {
00281 *ipPortRes = atoi(cpTempPort);
00282 if (*ipPortRes > 0) return true;
00283 }
00284 }
00285 return false;
00286 }
00287
00288
00289 clSoundUI::clSoundUI (int *ArgC, char ***ArgV)
00290 {
00291 int iInitCntr;
00292
00293 bRun = true;
00294 bFirstTimeout = true;
00295 lDataRefCount = 0L;
00296 for (iInitCntr = 0; iInitCntr < SUI_MAX_CHANNELS; iInitCntr++)
00297 {
00298 bpConnected[iInitCntr] = false;
00299 }
00300
00301 g_print("%s v%i.%i.%i\n", cpWindowTxt,
00302 SUI_VER_MAJ, SUI_VER_MIN, SUI_VER_PL);
00303 g_print("Copyright (C) 2000-2001 Jussi Laako\n\n");
00304 g_print("Gtk+ version %i.%i.%i\n", gtk_major_version, gtk_minor_version,
00305 gtk_micro_version);
00306 g_print("Locale set to %s\n", gtk_set_locale());
00307 gtk_init(ArgC, ArgV);
00308 }
00309
00310
00311 clSoundUI::~clSoundUI ()
00312 {
00313 }
00314
00315
00316 int clSoundUI::Exec ()
00317 {
00318 int iChBufSize;
00319 int iAllocCntr;
00320 double dNyquist;
00321 clDSPOp DSP;
00322
00323 GetCfg();
00324 if (iDeviceBase < 0)
00325 {
00326 pthread_create(&ptidSoundOut, NULL, WrapSoundOutThread, NULL);
00327 SemStart1.Wait();
00328 }
00329 iChBufSize = lSampleCount * sizeof(GDT);
00330 for (iAllocCntr = 0; iAllocCntr < iChCount; iAllocCntr++)
00331 {
00332 ChData[iAllocCntr].Size(iChBufSize);
00333 EqCoeffs[iAllocCntr].Size((lSampleCount + 1L) * sizeof(GDT));
00334 ChData[iAllocCntr].Lock();
00335 EqCoeffs[iAllocCntr].Lock();
00336 DSP.Zero((GDT *) ChData[iAllocCntr], lSampleCount);
00337 DSP.Set((GDT *) EqCoeffs[iAllocCntr], (GDT) 1.0, lSampleCount + 1L);
00338 fpLevelCoeff[iAllocCntr] = (GDT) 1.0;
00339 GDT *fpNullPtr = NULL;
00340 bpEqEnabled[iAllocCntr] = false;
00341 Filters[iAllocCntr].Initialize((long) lSampleCount, fpNullPtr,
00342 SUI_FILTER_WINDOW);
00343 }
00344 MutexData.Wait();
00345 dNyquist = iSampleRate / 2.0;
00346 iOctaveCount = (int) (log(dNyquist) / log(2.0) + 0.5);
00347 if (iOctaveCount > SUI_EQ_MAXOCTS) iOctaveCount = SUI_EQ_MAXOCTS;
00348 MutexData.Release();
00349 if (iDeviceBase < 0) SemStart2.Post();
00350 BuildGUI();
00351 gtk_timeout_add(iVuTimeout, WrapOnTimeoutEvent, NULL);
00352 gtk_main();
00353 if (iDeviceBase < 0) pthread_join(ptidSoundOut, NULL);
00354 for (iAllocCntr = 0; iAllocCntr < iChCount; iAllocCntr++)
00355 {
00356 MutexData.Wait();
00357 if (bpConnected[iAllocCntr])
00358 {
00359 bpConnected[iAllocCntr] = false;
00360 CondData[iAllocCntr].Notify();
00361 MutexData.Release();
00362 pthread_join(ptidSoundIn[iAllocCntr], NULL);
00363 }
00364 else MutexData.Release();
00365 }
00366 return 0;
00367 }
00368
00369
00370 gboolean clSoundUI::OnDeleteEvent (GtkWidget *gwSender, GdkEvent *geEvent,
00371 gpointer gpData)
00372 {
00373 MutexData.Wait();
00374 bRun = false;
00375 MutexData.Release();
00376 gtk_main_quit();
00377 return TRUE;
00378 }
00379
00380
00381 void clSoundUI::OnClickedEvent (GtkButton *gbButton, gpointer gpData)
00382 {
00383 int iChannel = GPOINTER_TO_INT(gpData);
00384 int iPort;
00385 int iSockHandle;
00386 int iSourceChannel;
00387 int iThreadMask;
00388 char cpServer[SUI_SERV_MAXLEN];
00389 GtkWidget *gwServerEntry;
00390
00391
00392 MutexData.Wait();
00393 if (bpConnected[iChannel])
00394 {
00395 bpConnected[iChannel] = false;
00396 MutexData.Release();
00397 pthread_join(ptidSoundIn[iChannel], NULL);
00398 }
00399 else MutexData.Release();
00400
00401 gwServerEntry = GTK_COMBO(SoundChGUI[iChannel]->gwCServer)->entry;
00402 iSourceChannel = gtk_spin_button_get_value_as_int(
00403 GTK_SPIN_BUTTON(SoundChGUI[iChannel]->gwSBChannel)) - 1;
00404 iThreadMask = ((iSourceChannel << 16) | iChannel);
00405
00406 if (ParseServerStr(cpServer, &iPort,
00407 gtk_entry_get_text(GTK_ENTRY(gwServerEntry))))
00408 {
00409 iSockHandle = SClient.Connect(cpServer, NULL, iPort);
00410 if (iSockHandle >= 0)
00411 {
00412 MutexData.Wait();
00413 bpConnected[iChannel] = true;
00414 ipSockH[iChannel] = iSockHandle;
00415 MutexData.Release();
00416 pthread_create(&ptidSoundIn[iChannel], NULL, WrapSoundInThread,
00417 GINT_TO_POINTER(iThreadMask));
00418 }
00419 else
00420 {
00421 g_print("Connect failed!\n");
00422 }
00423 }
00424 else
00425 {
00426 g_print("Invalid entry, format is <server>:<port>\n");
00427 }
00428 }
00429
00430
00431 gint clSoundUI::OnTimeoutEvent (gpointer gpData)
00432 {
00433 bool bTypeSet = false;
00434 int iLocalChCount;
00435 int iChCntr;
00436 gfloat fThisInLevel;
00437 gfloat fThisOutLevel;
00438
00439 MutexData.Wait();
00440 iLocalChCount = iChCount;
00441 MutexData.Release();
00442 for (iChCntr = 0; iChCntr < iLocalChCount; iChCntr++)
00443 {
00444 MutexLevel.Wait();
00445 fThisInLevel = fpInputLevel[iChCntr];
00446 fThisOutLevel = fpOutputLevel[iChCntr];
00447 MutexLevel.Release();
00448 gtk_progress_set_value(
00449 GTK_PROGRESS(SoundChGUI[iChCntr]->gwPBInputLevel), fThisInLevel);
00450 gtk_progress_set_value(
00451 GTK_PROGRESS(SoundChGUI[iChCntr]->gwPBOutputLevel), fThisOutLevel);
00452 if (bFirstTimeout &&
00453 GTK_WIDGET_REALIZED(SoundChGUI[iChCntr]->gwCurveEq))
00454 {
00455 gtk_curve_set_curve_type(GTK_CURVE(SoundChGUI[iChCntr]->gwCurveEq),
00456 GTK_CURVE_TYPE_LINEAR);
00457 bTypeSet = true;
00458 }
00459 }
00460 if (bTypeSet) bFirstTimeout = false;
00461 return TRUE;
00462 }
00463
00464
00465 void clSoundUI::OnToggledEvent (GtkToggleButton *gtbToggleButton,
00466 gpointer gpData)
00467 {
00468 bool bToggled;
00469 int iThisCh = GPOINTER_TO_INT(gpData);
00470
00471 bToggled =
00472 (gtk_toggle_button_get_active(gtbToggleButton)) ? true : false;
00473 MutexFilter[iThisCh].Wait();
00474 bpEqEnabled[iThisCh] = bToggled;
00475 MutexFilter[iThisCh].Release();
00476 }
00477
00478
00479 void clSoundUI::OnValueChangedEvent (GtkAdjustment *gaAdjustment,
00480 gpointer gpData)
00481 {
00482 int iThisCh;
00483 int iThisObj;
00484 long lCoeffCntr;
00485 long lCoeffCount;
00486 long lStartIdx;
00487 long lCenterIdx;
00488 long lEndIdx;
00489 long lDist;
00490 double dNyquist;
00491 double dResolution;
00492 GDT fValue;
00493 GDT fCoeff;
00494 GDT fPrevCoeff;
00495 GDT fNextCoeff;
00496 GDT fDiff;
00497 GDT *fpCoeffPtr;
00498
00499 iThisCh = (GPOINTER_TO_INT(gpData) >> 16);
00500 iThisObj = (GPOINTER_TO_INT(gpData) & 0xffff);
00501 fValue = -(gaAdjustment->value);
00502 fpCoeffPtr = EqCoeffs[iThisCh];
00503
00504 if (iThisObj == 0)
00505 {
00506 MutexFilter[iThisCh].Wait();
00507 fpLevelCoeff[iThisCh] = (GDT) pow(10.0, fValue / 20.0);
00508 MutexFilter[iThisCh].Release();
00509 return;
00510 }
00511
00512 MutexData.Wait();
00513 lCoeffCount = lSampleCount + 1L;
00514 dNyquist = iSampleRate / 2.0;
00515 MutexData.Release();
00516 dResolution = dNyquist / lCoeffCount;
00517 lStartIdx = (long) (pow(2.0, iThisObj - 1) / dResolution + 0.5);
00518 lCenterIdx = (long) (pow(2.0, iThisObj) / dResolution + 0.5);
00519 lEndIdx = (long) (pow(2.0, iThisObj + 1) / dResolution + 0.5);
00520 if (lStartIdx < 0) lStartIdx = 1L;
00521 if (lCenterIdx < 0) lCenterIdx = 1L;
00522 else if (lCenterIdx > lCoeffCount) lCenterIdx = lCoeffCount - 1L;
00523 if (lEndIdx > lCoeffCount) lEndIdx = lCoeffCount - 1L;
00524 fPrevCoeff = fpCoeffPtr[lStartIdx - 1L];
00525 fNextCoeff = fpCoeffPtr[lEndIdx];
00526 fCoeff = pow(10.0, fValue / 20.0);
00527 for (lCoeffCntr = lStartIdx; lCoeffCntr < lEndIdx; lCoeffCntr++)
00528 {
00529 if (lCoeffCntr < lCenterIdx)
00530 {
00531 fDiff = fCoeff - fPrevCoeff;
00532 lDist = lCenterIdx - lStartIdx;
00533 fpCoeffPtr[lCoeffCntr] =
00534 fPrevCoeff + fDiff / lDist * (lCoeffCntr - lStartIdx + 1);
00535 }
00536 else
00537 {
00538 fDiff = fCoeff - fNextCoeff;
00539 lDist = lEndIdx - lCenterIdx;
00540 fpCoeffPtr[lCoeffCntr] =
00541 fNextCoeff + fDiff / lDist * (lEndIdx - lCoeffCntr);
00542 }
00543 }
00544 if (iDCBlock > 0) fpCoeffPtr[0] = (GDT) 0.0;
00545 MutexFilter[iThisCh].Wait();
00546 Filters[iThisCh].SetCoeffs(fpCoeffPtr);
00547 MutexFilter[iThisCh].Release();
00548
00549 #ifdef __GNUG__
00550 gfloat fpCurveValues[lCoeffCount];
00551 #else
00552 gfloat *fpCurveValues;
00553 clDSPAlloc CurveValues;
00554 fpCurveValues = (gfloat *) CurveValues.Size(lCoeffCount * sizeof(gfloat));
00555 #endif
00556
00557 for (lCoeffCntr = 0L; lCoeffCntr < lCoeffCount; lCoeffCntr++)
00558 {
00559 fpCurveValues[lCoeffCntr] = 20.0 * log10(fpCoeffPtr[lCoeffCntr]);
00560 }
00561 gtk_curve_set_vector(GTK_CURVE(SoundChGUI[iThisCh]->gwCurveEq),
00562 lCoeffCount, fpCurveValues);
00563 gtk_curve_set_curve_type(GTK_CURVE(SoundChGUI[iThisCh]->gwCurveEq),
00564 GTK_CURVE_TYPE_LINEAR);
00565 }
00566
00567
00568 void clSoundUI::OnApplyCurveClicked (GtkButton *gbButton, gpointer gpData)
00569 {
00570 int iThisCh = GPOINTER_TO_INT(gpData);
00571 long lCoeffCntr;
00572 MutexData.Wait();
00573 long lCoeffCount = lSampleCount + 1L;
00574 MutexData.Release();
00575 #ifdef __GNUG__
00576 gfloat fpCurveValues[lCoeffCount];
00577 #else
00578 clDSPAlloc CurveValues;
00579 gfloat *fpCurveValues = (gfloat *)
00580 CurveValues.Size(lCoeffCount * sizeof(gfloat));
00581 #endif
00582 GDT *fpCoeffPtr = EqCoeffs[iThisCh];
00583
00584 gtk_curve_get_vector(GTK_CURVE(SoundChGUI[iThisCh]->gwCurveEq),
00585 lCoeffCount, fpCurveValues);
00586 for (lCoeffCntr = 0L; lCoeffCntr < lCoeffCount; lCoeffCntr++)
00587 {
00588 fpCoeffPtr[lCoeffCntr] =
00589 (GDT) pow(10.0, fpCurveValues[lCoeffCntr] / 20.0);
00590 }
00591 if (iDCBlock > 0) fpCoeffPtr[0] = (GDT) 0.0;
00592 MutexFilter[iThisCh].Wait();
00593 Filters[iThisCh].SetCoeffs(fpCoeffPtr);
00594 MutexFilter[iThisCh].Release();
00595 }
00596
00597
00598 void clSoundUI::OnMotionCurve (GtkWidget *gwSender, GdkEventMotion *gemEvent,
00599 gpointer gpData)
00600 {
00601 int iThisCh = GPOINTER_TO_INT(gpData);
00602 char cpStatusTxt[SUI_CONV_LEN];
00603 int iWidth;
00604 int iHeight;
00605 gfloat fResolution;
00606 gfloat fFreqScale;
00607 gfloat fHzValue;
00608 gfloat fdBValue;
00609
00610 iWidth = SoundChGUI[iThisCh]->gwCurveEq->allocation.width;
00611 iHeight = SoundChGUI[iThisCh]->gwCurveEq->allocation.height;
00612 MutexData.Wait();
00613 fResolution = iSampleRate / 2.0 / (lSampleCount + 1L);
00614 fFreqScale = (gfloat) (lSampleCount + 1L) / (gfloat) iWidth;
00615 MutexData.Release();
00616 fHzValue = gemEvent->x * fFreqScale * fResolution;
00617 fdBValue = (iHeight - gemEvent->y) * (SUI_EQ_RANGE * 2.0 / iHeight) -
00618 SUI_EQ_RANGE;
00619 g_snprintf(cpStatusTxt, SUI_CONV_LEN, "%.1f Hz %.2f dB",
00620 fHzValue, fdBValue);
00621 gtk_statusbar_pop(GTK_STATUSBAR(gwStatusbar), guiStatusbarCtxt);
00622 gtk_statusbar_push(GTK_STATUSBAR(gwStatusbar), guiStatusbarCtxt,
00623 cpStatusTxt);
00624 }
00625
00626
00627 void *clSoundUI::SoundOutThread (void *vpData)
00628 {
00629 bool bLocalRun = true;
00630 #ifndef __QNX__
00631 int iFormat = SUI_SND_FORMAT;
00632 #endif
00633 int iLocalCh;
00634 int iLocalSR;
00635
00636 MutexData.Wait();
00637 iLocalCh = iChCount;
00638 iLocalSR = iSampleRate;
00639 MutexData.Release();
00640 if (!bALSA)
00641 {
00642 #ifndef __QNX__
00643 if (Audio.Open(cpDevice, &iFormat, &iLocalSR, &iLocalCh, AUDIO_WRITE))
00644 {
00645 g_print("Audio device open; fs %i ch %i fmt %xh\n", iLocalSR,
00646 iLocalCh, iFormat);
00647 MutexData.Wait();
00648 iChCount = iLocalCh;
00649 iSampleRate = iLocalSR;
00650 MutexData.Release();
00651 }
00652 else
00653 {
00654 g_print("Unable to open audio device, reason: %s\n",
00655 strerror(Audio.GetError()));
00656 bLocalRun = false;
00657 }
00658 #else
00659 g_warning("OSS is not supported under QNX");
00660 #endif
00661 }
00662 else
00663 {
00664 #ifndef BSDSYS
00665 if (AudioA.CardOpen(iALSACard))
00666 {
00667 #ifdef USE_ALSA05
00668 if (AudioA.PcmOpen(iALSADevice, iALSASubDevice, AA_MODE_PLAY))
00669 #else
00670 sprintf(cpDevice, "plughw:%i,%i", iALSACard, iALSADevice);
00671 if (AudioA.PcmOpen(cpDevice, AA_MODE_PLAY))
00672 #endif
00673 {
00674 #ifdef USE_ALSA05
00675 if (AudioA.PcmSetSetup(iLocalCh, iLocalSR, SUI_SND_BITS,
00676 SUI_SND_QUEUESIZE, false))
00677 #else
00678 if (AudioA.PcmSetSetup(iLocalCh, iLocalSR, SUI_SND_BITS,
00679 SUI_SND_QUEUESIZE, 2))
00680 #endif
00681 {
00682 if (AudioA.PcmPrepare())
00683 {
00684 iLocalCh = AudioA.PcmGetChannels();
00685 iLocalSR = AudioA.PcmGetSampleRate();
00686 g_print("Audio device open; fs %i ch %i wl %i\n",
00687 iLocalSR, iLocalCh,
00688 AudioA.PcmGetBits());
00689 MutexData.Wait();
00690 iChCount = iLocalCh;
00691 iSampleRate = iLocalSR;
00692 MutexData.Release();
00693 }
00694 else
00695 {
00696 g_print("ALSA PCM prepare failed\n");
00697 bLocalRun = false;
00698 }
00699 }
00700 else
00701 {
00702 g_print("ALSA PCM setup failed\n");
00703 g_print("%s\n", AudioA.PcmGetStatusStr(AudioA.PcmGetStatus()));
00704 bLocalRun = false;
00705 }
00706 }
00707 else
00708 {
00709 g_print("ALSA PCM open failed\n");
00710 bLocalRun = false;
00711 }
00712 }
00713 else
00714 {
00715 g_print("ALSA card open failed\n");
00716 bLocalRun = false;
00717 }
00718 #else
00719 g_warning("ALSA not supported under BSD systems");
00720 #endif
00721 }
00722 SemStart1.Post();
00723 SemStart2.Wait();
00724
00725 long lChMask;
00726 long lChCntr;
00727 long lSampleCntr;
00728 long lLocalSC;
00729 volatile long lLocalRefCount;
00730 long lOutDataCount;
00731 long lOutBufSize;
00732 GDT *fpChBuf;
00733 GDT *fpOutBuf;
00734 SUI_SND_DATATYPE *ipOutBuf;
00735
00736 #ifndef BSDSYS
00737 int iSchedPolicy;
00738 uid_t uidCurrent;
00739 struct sched_param sSchedParam;
00740 #endif
00741
00742 clDSPAlloc OutBuf1;
00743 clDSPAlloc OutBuf2;
00744 clDSPOp DSP;
00745
00746 MutexData.Wait();
00747 lLocalSC = lSampleCount;
00748 MutexData.Release();
00749 lOutDataCount = lLocalSC * iLocalCh;
00750 fpOutBuf = (GDT *) OutBuf1.Size(lOutDataCount * sizeof(GDT));
00751 lOutBufSize = lLocalSC * iLocalCh * sizeof(SUI_SND_DATATYPE);
00752 ipOutBuf = (SUI_SND_DATATYPE *) OutBuf2.Size(lOutBufSize);
00753 OutBuf1.Lock();
00754 OutBuf2.Lock();
00755 #ifndef BSDSYS
00756 uidCurrent = getuid();
00757 setuid(0);
00758 pthread_getschedparam(ptidSoundOut, &iSchedPolicy, &sSchedParam);
00759 sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO) + 2;
00760 if (pthread_setschedparam(ptidSoundOut, SCHED_FIFO, &sSchedParam) != 0)
00761 {
00762 g_print("SoundOut unable to set scheduling policy\n");
00763 }
00764 setuid(uidCurrent);
00765
00766
00767 #endif
00768 g_print("SoundOut thread running\n");
00769 DSP.Zero(fpOutBuf, lOutDataCount);
00770 #ifndef BSDSYS
00771 #ifdef USE_ALSA05
00772 if (bALSA) AudioA.PcmGo();
00773 #else
00774 if (bALSA) AudioA.PcmStart();
00775 #endif
00776 #endif
00777 while (bLocalRun)
00778 {
00779 for (lChCntr = 0; lChCntr < iLocalCh; lChCntr++)
00780 {
00781 lChMask = (1L << lChCntr);
00782 MutexData.Wait();
00783 lLocalRefCount = lDataRefCount;
00784 MutexData.Release();
00785
00786
00787
00788 if (!(lLocalRefCount & lChMask))
00789 {
00790 usleep((unsigned long) (lLocalSC / 2 / iLocalSR * 1000000));
00791 MutexData.Wait();
00792 lLocalRefCount = lDataRefCount;
00793 MutexData.Release();
00794 }
00795
00796 if ((lLocalRefCount & lChMask) == lChMask)
00797 {
00798 MutexChData[lChCntr].Wait();
00799 fpChBuf = ChData[lChCntr];
00800 for (lSampleCntr = 0; lSampleCntr < lLocalSC; lSampleCntr++)
00801 {
00802 fpOutBuf[lSampleCntr * iLocalCh + lChCntr] =
00803 fpChBuf[lSampleCntr];
00804 }
00805 MutexData.Wait();
00806 lDataRefCount &= ~(lChMask);
00807 MutexData.Release();
00808 CondData[lChCntr].Notify();
00809 MutexChData[lChCntr].Release();
00810 }
00811 else
00812 {
00813 for (lSampleCntr = 0; lSampleCntr < lLocalSC; lSampleCntr++)
00814 {
00815 fpOutBuf[lSampleCntr * iLocalCh + lChCntr] = (GDT) 0.0;
00816 }
00817 MutexChData[lChCntr].Wait();
00818 CondData[lChCntr].Notify();
00819 MutexChData[lChCntr].Release();
00820 }
00821 }
00822 DSP.Convert(ipOutBuf, fpOutBuf, lOutDataCount, false);
00823 if (!bALSA)
00824 {
00825 #ifndef __QNX__
00826 if (Audio.Write(ipOutBuf, lOutBufSize) < lOutBufSize)
00827 g_warning("Write to PCM device failed!");
00828 #endif
00829 }
00830 else
00831 {
00832 #ifndef BSDSYS
00833
00834
00835 AudioA.PcmWrite(ipOutBuf, lOutBufSize);
00836 #endif
00837 }
00838 MutexData.Wait();
00839 bLocalRun = bRun;
00840 MutexData.Release();
00841 }
00842 if (!bALSA)
00843 {
00844 #ifndef __QNX__
00845 Audio.Reset();
00846 Audio.Close();
00847 #endif
00848 }
00849 else
00850 {
00851 #ifndef BSDSYS
00852 AudioA.PcmClose();
00853 AudioA.CardClose();
00854 #endif
00855 }
00856 g_print("SoundOut thread ending\n");
00857 return NULL;
00858 }
00859
00860
00861 void *clSoundUI::SoundInThread (void *vpData)
00862 {
00863 bool bLocalRun = true;
00864 int iSrcCh = (GPOINTER_TO_INT(vpData) >> 16);
00865 int iDestCh = (GPOINTER_TO_INT(vpData) & 0xffff);
00866 int iThisIdx = iDestCh;
00867 int iLocalChCount;
00868 long lLocalSC;
00869 int iMsgSize;
00870 char *cpMsgBuf;
00871 char cpHdrBuf[GLOBAL_HEADER_LEN];
00872 stSoundStart sSoundHdr;
00873 clAlloc MsgBuf;
00874 clSoundMsg SoundMsg;
00875 clSockOp SOp;
00876
00877 MutexData.Wait();
00878 iLocalChCount = iChCount;
00879 lLocalSC = lSampleCount;
00880 SOp.SetHandle(ipSockH[iThisIdx]);
00881 MutexData.Release();
00882 g_print("SoundIn[%i] thread receiving first message...\n", iThisIdx);
00883 if (SOp.ReadSelect(SUI_FIRST_TIMEOUT))
00884 {
00885 if (SOp.ReadN(cpHdrBuf, GLOBAL_HEADER_LEN) == GLOBAL_HEADER_LEN)
00886 {
00887 SoundMsg.GetStart(cpHdrBuf, &sSoundHdr);
00888 }
00889 else bLocalRun = false;
00890 }
00891 iMsgSize = lLocalSC * sSoundHdr.iChannels * sizeof(GDT);
00892 cpMsgBuf = (char *) MsgBuf.Size(iMsgSize);
00893 MsgBuf.Lock();
00894
00895 bool bWait;
00896 #ifndef __QNX__
00897 int iLocalFmt = SUI_SND_FORMAT;
00898 #endif
00899 int iLocalSR = (int) (sSoundHdr.dSampleRate + 0.5);
00900 int iLocalCh = iChCount;
00901 long lExtCount = lLocalSC * sSoundHdr.iChannels;
00902 long lOutCount = lLocalSC;
00903 long lChMask = (1L << iThisIdx);
00904 #ifndef __QNX__
00905 long lOutBufSize = 0L;
00906 long lSampleCntr;
00907 char cpDeviceName[_POSIX_PATH_MAX];
00908 #endif
00909 gfloat fInLevel;
00910 gfloat fOutLevel;
00911 GDT *fpInBuf;
00912 GDT *fpOutData;
00913 #ifndef __QNX__
00914 SUI_SND_DATATYPE *ipOutData = NULL;
00915 SUI_SND_DATATYPE *ipOutBuf = NULL;
00916 audio_buf_info sAudioBufInfo;
00917 #endif
00918
00919 #ifndef BSDSYS
00920 int iSchedPolicy;
00921 uid_t uidCurrent;
00922 struct sched_param sSchedParam;
00923 #endif
00924
00925 clDSPAlloc InBuf;
00926 clDSPAlloc OutData1;
00927 clDSPAlloc OutData2;
00928 clDSPAlloc OutBuf;
00929 #ifndef __QNX__
00930 clAudio Audio;
00931 #endif
00932 clDSPOp DSP;
00933
00934 if (iDeviceBase >= 0)
00935 {
00936 #ifndef __QNX__
00937 g_snprintf(cpDeviceName, _POSIX_PATH_MAX, "%s%i",
00938 cpDevice, iDeviceBase + iDestCh);
00939 g_print("SoundIn[%i] open device %s : %i fs\n",
00940 iThisIdx, cpDeviceName, iLocalSR);
00941 if (!Audio.Open(cpDeviceName, &iLocalFmt, &iLocalSR, &iLocalCh,
00942 AUDIO_WRITE))
00943 {
00944 g_print("Fatal: failed to open device %s in SoundIn[%i]\n",
00945 cpDeviceName, iThisIdx);
00946 return NULL;
00947 }
00948 g_print("SoundIn[%i] device opened at %i fs\n", iThisIdx, iLocalSR);
00949 lOutBufSize = lOutCount * iLocalCh * sizeof(SUI_SND_DATATYPE);
00950 ipOutData = (SUI_SND_DATATYPE *) OutData2.Size(lOutCount * sizeof(SUI_SND_DATATYPE));
00951 ipOutBuf = (SUI_SND_DATATYPE *) OutBuf.Size(lOutBufSize);
00952 OutData2.Lock();
00953 OutBuf.Lock();
00954 memset(ipOutBuf, 0x00, lOutBufSize);
00955 #else
00956 g_warning("This functionality is not supported under QNX");
00957 #endif
00958 }
00959 SOp.SetRecvBufSize(iMsgSize * 2);
00960 fpInBuf = (GDT *) InBuf.Size(lExtCount * sizeof(GDT));
00961 fpOutData = (GDT *) OutData1.Size(lOutCount * sizeof(GDT));
00962 InBuf.Lock();
00963 OutData1.Lock();
00964 #ifndef BSDSYS
00965 uidCurrent = getuid();
00966 setuid(0);
00967 pthread_getschedparam(ptidSoundOut, &iSchedPolicy, &sSchedParam);
00968 sSchedParam.sched_priority = sched_get_priority_min(SCHED_FIFO) + 1;
00969 if (pthread_setschedparam(ptidSoundOut, SCHED_FIFO, &sSchedParam) != 0)
00970 {
00971 g_print("SoundIn[%i] unable to set scheduling policy\n", iThisIdx);
00972 }
00973 setuid(uidCurrent);
00974
00975
00976 #endif
00977 g_print("SoundIn[%i] thread running\n", iThisIdx);
00978 #ifndef __QNX__
00979 if (iDeviceBase >= 0)
00980 {
00981 g_print("SoundIn[%i] prefilling output buffer...\n", iThisIdx);
00982 do {
00983 Audio.Write(ipOutBuf, lOutBufSize);
00984 Audio.GetOutBufInfo(&sAudioBufInfo);
00985 } while (sAudioBufInfo.bytes >= lOutBufSize);
00986 }
00987 #endif
00988
00989
00990
00991 float fTime = 1.0f / (iLocalSR * iLocalCh);
00992 usleep((unsigned long) (lExtCount * fTime * 1000000.0f + 0.5f));
00993 while (bLocalRun)
00994 {
00995 if (SOp.ReadSelect(SUI_IN_TIMEOUT))
00996 {
00997 if (SOp.ReadN(cpMsgBuf, iMsgSize) == iMsgSize)
00998 {
00999 SoundMsg.GetData(cpMsgBuf, fpInBuf, lExtCount);
01000 DSP.Extract(fpOutData, fpInBuf, iSrcCh, sSoundHdr.iChannels,
01001 lExtCount);
01002 fInLevel = DSP.PeakLevel(fpOutData, lOutCount);
01003 MutexLevel.Wait();
01004 fpInputLevel[iThisIdx] =
01005 (fpInputLevel[iThisIdx] + fInLevel) * (gfloat) 0.5;
01006 MutexLevel.Release();
01007 MutexFilter[iThisIdx].Wait();
01008 DSP.Mul(fpOutData, fpLevelCoeff[iThisIdx], lOutCount);
01009 if (bpEqEnabled[iThisIdx])
01010 {
01011 Filters[iThisIdx].Put(fpOutData, lOutCount);
01012 if (!Filters[iThisIdx].Get(fpOutData, lOutCount))
01013 DSP.Zero(fpOutData, lOutCount);
01014 }
01015 MutexFilter[iThisIdx].Release();
01016 fOutLevel = DSP.PeakLevel(fpOutData, lOutCount);
01017 MutexLevel.Wait();
01018 fpOutputLevel[iThisIdx] =
01019 (fpOutputLevel[iThisIdx] + fOutLevel) *
01020 (gfloat) 0.5;
01021 MutexLevel.Release();
01022 if (iDeviceBase < 0)
01023 {
01024 MutexData.Wait();
01025 bWait = ((lDataRefCount & lChMask) == lChMask) ?
01026 true : false;
01027 MutexData.Release();
01028 MutexChData[iThisIdx].Wait();
01029 if (bWait)
01030 {
01031 CondData[iThisIdx].Wait(
01032 MutexChData[iThisIdx].GetPtr());
01033 }
01034 DSP.Copy((GDT *) ChData[iThisIdx], fpOutData, lOutCount);
01035 MutexData.Wait();
01036 lDataRefCount |= lChMask;
01037 bLocalRun = bpConnected[iThisIdx];
01038 MutexData.Release();
01039 MutexChData[iThisIdx].Release();
01040 }
01041 #ifndef __QNX__
01042 else
01043 {
01044 DSP.Convert(ipOutData, fpOutData, lOutCount, false);
01045 for (lSampleCntr = 0L;
01046 lSampleCntr < lOutCount;
01047 lSampleCntr++)
01048 {
01049 ipOutBuf[lSampleCntr * iLocalCh + iDestCh] =
01050 ipOutData[lSampleCntr];
01051 }
01052 Audio.Write(ipOutBuf, lOutBufSize);
01053 MutexData.Wait();
01054 bLocalRun = bpConnected[iThisIdx];
01055 MutexData.Release();
01056 }
01057 #endif
01058 }
01059 else bLocalRun = false;
01060 }
01061 else
01062 {
01063 if (SOp.GetErrno() != 0) bLocalRun = false;
01064 }
01065 MutexData.Wait();
01066 bLocalRun = bpConnected[iThisIdx];
01067 MutexData.Release();
01068 }
01069 SOp.Close();
01070 MutexData.Wait();
01071 bpConnected[iThisIdx] = false;
01072 MutexData.Release();
01073 #ifndef __QNX__
01074 if (iDeviceBase >= 0)
01075 {
01076 Audio.Reset();
01077 Audio.Close();
01078 }
01079 #endif
01080 g_print("SoundIn[%i] thread ending\n", iThisIdx);
01081 return NULL;
01082 }
01083
01084
01085
01086
01087
01088 clSoundChGUI::clSoundChGUI (GtkWidget *gwAttachBox, int iChannelNo,
01089 int iOctaveCount, long lFilterSize)
01090 {
01091 int iOctaveCntr;
01092 char cpConvBuf[SUI_CONV_LEN];
01093 gfloat fFreq;
01094
01095 g_snprintf(cpConvBuf, SUI_CONV_LEN, "%s %i", cpChannelPfx, iChannelNo);
01096 gwFrame = gtk_frame_new(cpConvBuf);
01097
01098 gtk_box_pack_start(GTK_BOX(gwAttachBox), gwFrame, TRUE, TRUE, 0);
01099 gtk_widget_show(gwFrame);
01100
01101 gwVBox = gtk_vbox_new(FALSE, SUI_PADDING);
01102 gtk_container_add(GTK_CONTAINER(gwFrame), gwVBox);
01103 gtk_widget_show(gwVBox);
01104
01105
01106
01107 gwTable1 = gtk_table_new(2, 3, FALSE);
01108 gtk_box_pack_start(GTK_BOX(gwVBox), gwTable1, FALSE, FALSE, 0);
01109 gtk_widget_show(gwTable1);
01110
01111 gwLServer = gtk_label_new(cpLServerTxt);
01112 gtk_label_set_justify(GTK_LABEL(gwLServer), GTK_JUSTIFY_LEFT);
01113 gtk_table_attach(GTK_TABLE(gwTable1), gwLServer,
01114 0, 1, 0, 1,
01115 (GtkAttachOptions) (GTK_FILL|GTK_SHRINK|GTK_EXPAND),
01116 (GtkAttachOptions) 0,
01117 SUI_PADDING / 2, 0);
01118 gtk_widget_show(gwLServer);
01119 gwCServer = gtk_combo_new();
01120 gtk_entry_set_max_length(GTK_ENTRY(GTK_COMBO(gwCServer)->entry),
01121 SUI_SERV_MAXLEN);
01122 gtk_table_attach(GTK_TABLE(gwTable1), gwCServer,
01123 0, 1, 1, 2,
01124 (GtkAttachOptions) (GTK_FILL|GTK_SHRINK|GTK_EXPAND),
01125 (GtkAttachOptions) 0,
01126 SUI_PADDING / 2, 0);
01127 gtk_widget_show(gwCServer);
01128 glServers = NULL;
01129 GtkUtils.ComboListFromFile(gwCServer, &glServers, SUI_HOSTFILE);
01130
01131 gwLChannel = gtk_label_new(cpLChannelTxt);
01132 gtk_label_set_justify(GTK_LABEL(gwLChannel), GTK_JUSTIFY_LEFT);
01133 gtk_table_attach(GTK_TABLE(gwTable1), gwLChannel,
01134 1, 2, 0, 1,
01135 (GtkAttachOptions) 0,
01136 (GtkAttachOptions) 0,
01137 SUI_PADDING / 2, 0);
01138 gtk_widget_show(gwLChannel);
01139
01140 goAChannel = gtk_adjustment_new(SUI_CH_VALUE, SUI_CH_LOWER, SUI_CH_HIGHER,
01141 1.0, 1.0, 1.0);
01142
01143 gwSBChannel = gtk_spin_button_new(GTK_ADJUSTMENT(goAChannel),
01144 1.0, 0);
01145 gtk_table_attach(GTK_TABLE(gwTable1), gwSBChannel,
01146 1, 2, 1, 2,
01147 (GtkAttachOptions) 0,
01148 (GtkAttachOptions) 0,
01149 SUI_PADDING / 2, 0);
01150 gtk_widget_show(gwSBChannel);
01151
01152 gwBConnect = gtk_button_new_with_label(cpBConnectTxt);
01153 gtk_table_attach(GTK_TABLE(gwTable1), gwBConnect,
01154 2, 3, 1, 2,
01155 (GtkAttachOptions) 0,
01156 (GtkAttachOptions) 0,
01157 SUI_PADDING / 2, 0);
01158 gtk_widget_show(gwBConnect);
01159
01160 gwLInputLevel = gtk_label_new(cpLInputLevelTxt);
01161 gtk_label_set_justify(GTK_LABEL(gwLInputLevel), GTK_JUSTIFY_LEFT);
01162 gtk_box_pack_start(GTK_BOX(gwVBox), gwLInputLevel, FALSE, FALSE, 0);
01163 gtk_widget_show(gwLInputLevel);
01164 gwPBInputLevel = gtk_progress_bar_new();
01165 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(gwPBInputLevel),
01166 GTK_PROGRESS_LEFT_TO_RIGHT);
01167 gtk_progress_set_show_text(GTK_PROGRESS(gwPBInputLevel), TRUE);
01168 gtk_progress_set_text_alignment(GTK_PROGRESS(gwPBInputLevel),
01169 0.0, 0.5);
01170 gtk_progress_set_format_string(GTK_PROGRESS(gwPBInputLevel),
01171 "%v dB");
01172
01173 gtk_progress_configure(GTK_PROGRESS(gwPBInputLevel),
01174 SUI_IN_VALUE, SUI_IN_LOWER, SUI_IN_HIGHER);
01175 gtk_box_pack_start(GTK_BOX(gwVBox), gwPBInputLevel, FALSE, FALSE, 0);
01176 gtk_widget_show(gwPBInputLevel);
01177
01178 gwCBEq = gtk_check_button_new_with_label(cpLEqTxt);
01179 gtk_box_pack_start(GTK_BOX(gwVBox), gwCBEq, FALSE, FALSE, 0);
01180 gtk_widget_show(gwCBEq);
01181 gwTableEq = gtk_table_new(2, iOctaveCount, FALSE);
01182 gtk_box_pack_start(GTK_BOX(gwVBox), gwTableEq, TRUE, TRUE, 0);
01183 gtk_widget_show(gwTableEq);
01184 gwLOutputLevel = gtk_label_new(cpLOutputLevelTxt);
01185 gtk_table_attach(GTK_TABLE(gwTableEq), gwLOutputLevel,
01186 0, 1, 1, 2,
01187 (GtkAttachOptions) (GTK_SHRINK|GTK_EXPAND),
01188 (GtkAttachOptions) 0,
01189 SUI_PADDING / 2, 0);
01190 gtk_widget_show(gwLOutputLevel);
01191 goAOutputLevel = gtk_adjustment_new(0.0, -(SUI_OUT_RANGE), SUI_OUT_RANGE,
01192 SUI_OUT_STEP, 1.0, 1.0);
01193 gwVSOutputLevel = gtk_vscale_new(GTK_ADJUSTMENT(goAOutputLevel));
01194 gtk_scale_set_draw_value(GTK_SCALE(gwVSOutputLevel), FALSE);
01195 gtk_table_attach(GTK_TABLE(gwTableEq), gwVSOutputLevel,
01196 0, 1, 0, 1,
01197 (GtkAttachOptions) (GTK_SHRINK|GTK_EXPAND),
01198 (GtkAttachOptions) (GTK_FILL|GTK_SHRINK|GTK_EXPAND),
01199 SUI_PADDING / 2, 0);
01200 gtk_widget_show(gwVSOutputLevel);
01201 gwPBOutputLevel = gtk_progress_bar_new();
01202 gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(gwPBOutputLevel),
01203 GTK_PROGRESS_BOTTOM_TO_TOP);
01204 gtk_progress_set_show_text(GTK_PROGRESS(gwPBOutputLevel), TRUE);
01205 gtk_progress_set_text_alignment(GTK_PROGRESS(gwPBOutputLevel),
01206 0.5, 1.0);
01207 gtk_progress_set_format_string(GTK_PROGRESS(gwPBOutputLevel),
01208 "%v dB");
01209
01210 gtk_progress_configure(GTK_PROGRESS(gwPBOutputLevel),
01211 SUI_OUT_VALUE, SUI_OUT_LOWER, SUI_OUT_HIGHER);
01212 gtk_table_attach(GTK_TABLE(gwTableEq), gwPBOutputLevel,
01213 1, 2, 0, 2,
01214 (GtkAttachOptions) (GTK_SHRINK|GTK_EXPAND),
01215 (GtkAttachOptions) (GTK_FILL|GTK_SHRINK|GTK_EXPAND),
01216 SUI_PADDING / 2, 0);
01217 gtk_widget_show(gwPBOutputLevel);
01218 for (iOctaveCntr = 0; iOctaveCntr < iOctaveCount; iOctaveCntr++)
01219 {
01220 fFreq = pow(2.0, iOctaveCntr + 1);
01221 if (fFreq < 1000.0)
01222 g_snprintf(cpConvBuf, SUI_CONV_LEN, "%.0f", fFreq);
01223 else
01224 g_snprintf(cpConvBuf, SUI_CONV_LEN, "%.1fk", fFreq / 1000.0);
01225 gwaLEqLevel[iOctaveCntr] = gtk_label_new(cpConvBuf);
01226 gtk_table_attach(GTK_TABLE(gwTableEq), gwaLEqLevel[iOctaveCntr],
01227 2 + iOctaveCntr, 3 + iOctaveCntr, 1, 2,
01228 (GtkAttachOptions) (GTK_SHRINK|GTK_EXPAND),
01229 (GtkAttachOptions) 0,
01230 SUI_PADDING / 2, 0);
01231 gtk_widget_show(gwaLEqLevel[iOctaveCntr]);
01232 goaAEqLevel[iOctaveCntr] = gtk_adjustment_new(
01233 0.0, -(SUI_EQ_RANGE), SUI_EQ_RANGE, SUI_EQ_STEP, 1.0, 1.0);
01234 gwaVSEqLevel[iOctaveCntr] = gtk_vscale_new(
01235 GTK_ADJUSTMENT(goaAEqLevel[iOctaveCntr]));
01236 gtk_scale_set_draw_value(GTK_SCALE(gwaVSEqLevel[iOctaveCntr]), FALSE);
01237 gtk_table_attach(GTK_TABLE(gwTableEq), gwaVSEqLevel[iOctaveCntr],
01238 2 + iOctaveCntr, 3 + iOctaveCntr, 0, 1,
01239 (GtkAttachOptions) (GTK_SHRINK|GTK_EXPAND),
01240 (GtkAttachOptions) (GTK_FILL|GTK_SHRINK|GTK_EXPAND),
01241 SUI_PADDING / 2, 0);
01242 gtk_widget_show(gwaVSEqLevel[iOctaveCntr]);
01243 }
01244
01245
01246 gwCurveEq = gtk_curve_new();
01247 gtk_box_pack_start(GTK_BOX(gwVBox), gwCurveEq, TRUE, TRUE, 0);
01248 gtk_curve_set_range(GTK_CURVE(gwCurveEq),
01249 0.0, (gfloat) lFilterSize,
01250 -SUI_EQ_RANGE, SUI_EQ_RANGE);
01251
01252 #ifdef __GNUG__
01253 GDT fpInitVect[lFilterSize];
01254 #else
01255 clDSPAlloc InitVect;
01256 GDT *fpInitVect = (GDT *) InitVect.Size(lFilterSize * sizeof(GDT));
01257 #endif
01258 clDSPOp DSP;
01259
01260 DSP.Set(fpInitVect, 0.0, lFilterSize);
01261 gtk_curve_set_vector(GTK_CURVE(gwCurveEq), lFilterSize, fpInitVect);
01262 gtk_widget_set_usize(gwCurveEq, gwCurveEq->requisition.width,
01263 gwCurveEq->requisition.width);
01264 gtk_widget_show(gwCurveEq);
01265
01266
01267 gwBApplyCurve = gtk_button_new_with_label(cpBApplyCurveTxt);
01268 gtk_box_pack_start(GTK_BOX(gwVBox), gwBApplyCurve, FALSE, FALSE, 0);
01269 gtk_widget_show(gwBApplyCurve);
01270 }
01271
01272
01273 clSoundChGUI::~clSoundChGUI ()
01274 {
01275 }
01276