// If you want to see what WSJT-X is putting in its common block // for its jt9.exe, then this button is useful // Set a break down in the native code it calls and the // debugger will show you the FORTRAN common block. private void buttonSpy_Click(object sender, EventArgs e) { var sharedMem = new XDft.WsjtSharedMemory("WSJT-X", true); sharedMem.Spy(); sharedMem.Dispose(); }
private void MainForm_FormClosed(object sender, FormClosedEventArgs e) { /* Failure to call Dispose will keep certain Windows handles * on, for example, shared memory, active for an interminate amount * of time before garbage collection. Its OK to fail if this process * is exiting: the OS will clean up. But if your process instances * multiple forms, then you had better do the Dispose's */ if (demodulator != null) { demodulator.Dispose(); } demodulator = null; if (wsjtExe != null) { wsjtExe.Dispose(); } wsjtExe = null; if (wsjtSharedMem != null) { wsjtSharedMem.Dispose(); } wsjtSharedMem = null; if (waveDevicePlayer != null) { waveDevicePlayer.Dispose(); } waveDevicePlayer = null; }
private XDft.RxSinkRepeater rxSinkRepeater; // need help repeating the RX audio to each decoder // have to know at construction time how many decoders public MultiDemodulatorWrapper(int instanceNumber, uint numDemodulators = 1) { if (numDemodulators > MAX_MULTIPROC) { numDemodulators = (uint)MAX_MULTIPROC; } if (numDemodulators == 0) { numDemodulators = 1; } demodulators = new XDft.Demodulator[numDemodulators]; wsjtSharedMems = new XDft.WsjtSharedMemory[numDemodulators]; wsjtExes = new XDft.WsjtExe[numDemodulators]; enabled = new bool[numDemodulators]; sharedMemoryKeys = new string[numDemodulators]; for (uint i = 0; i < numDemodulators; i++) { demodulators[i] = new XDft.Demodulator(); enabled[i] = true; // The first decoder gets the same subdirectory name as a single decoder string sharedMemoryKey = "DigiRite-" + instanceNumber.ToString(); if (i != 0) // subsequent ones get extra goop in their names { sharedMemoryKey += "-" + i.ToString(); } wsjtSharedMems[i] = new XDft.WsjtSharedMemory(sharedMemoryKey, false); if (!wsjtSharedMems[i].CreateWsjtSharedMem()) { throw new System.Exception("Failed to create Shared Memory from " + sharedMemoryKey); } // The subprocess itself is managed by the XDft wsjtExes[i] = new XDft.WsjtExe(); wsjtExes[i].AppDataName = sharedMemoryKey; sharedMemoryKeys[i] = sharedMemoryKey; if (!wsjtExes[i].CreateWsjtProcess(wsjtSharedMems[i])) { Dispose(); throw new System.Exception("Failed to launch wsjt exe"); } } multibandManager = new MultibandManagerOneDemod(demodulators); }
/* Note to programmers reading this for the first time: * Please do NOT be intimidated by all the comments in InitDemodulator! * They describe everything in gory detail. All you MUST know is this: * Instance these three objects from the XDft8 namespace: * Demodulator * WsjtSharedMemory * WsjtExe * * For the last two, choose the names in their properties carefully IF you * are going to run multiple instances of the Demodulator on the same PC. * * Set the Demodulator's callback delegate for decoded messages. * ...and do nothing more at initialization time. * * You also need a timer to call Demodulator.Clock(). See below. */ private void InitDemodulator(SetupForm sf) { // The objects implement IDisposable. If you fail to // dispose of one you quit using, its Windows resources // remain allocated until garbage collection. if (null != demodulator) { demodulator.Dispose(); } demodulator = null; if (null != wsjtSharedMem) { wsjtSharedMem.Dispose(); } wsjtSharedMem = null; if (null != wsjtExe) { wsjtExe.Dispose(); } wsjtExe = null; if (null != waveDevicePlayer) { waveDevicePlayer.Dispose(); } waveDevicePlayer = null; // The demodulator invokes the wsjtx decoder demodulator = new XDft.Demodulator(); // the names of its parameters are verbatim from the wsjt-x source code. // Don't ask this author what they mean. demodulator.nftx = 1500; demodulator.nfqso = 1500; demodulator.nQSOProgress = 5; demodulator.nzhsym = digiMode == XDft.DigiMode.DIGI_FT8 ? 50 : 18; mycall = sf.myCall.ToUpper(); demodulator.mycall = mycall; if (xmitForm != null) { xmitForm.mycall = mycall; } demodulator.digiMode = digiMode; // When the decoder finds an FT8 message, it calls us back... // ...on a foreign thread. Call BeginInvoke to get back on this one. See below. demodulator.DemodulatorResultCallback = new XDft.DemodResult(Decoded); // The wsjt-x code is run in a subprocess and we communicate with it using // cross-process shared memory. Such a construct requires the parent/sub-process // to agree on a name. That name must be unique to all the parent/sub's running // concurrently. That means that whatever name you give here must NOT // also be given to a copy of this programming running concurrently on the // same PC. For the test program, we leave it up to the user in the setup form. // that is a VERY bad idea for production...you have been warned. wsjtSharedMem = new XDft.WsjtSharedMemory(sf.sharedMemoryKey, false); if (!wsjtSharedMem.CreateWsjtSharedMem()) { MessageBox.Show("Failed to create Shared Memory from " + sf.sharedMemoryKey); return; } // The subprocess itself is managed by the XDft wsjtExe = new XDft.WsjtExe(); wsjtExe.AppDataName = sf.appDataName; if (!wsjtExe.CreateWsjtProcess(wsjtSharedMem)) { MessageBox.Show("Failed to launch wsjt exe"); demodulator.Dispose(); wsjtExe.Dispose(); wsjtExe = null; wsjtSharedMem.Dispose(); wsjtSharedMem = null; demodulator = null; return; } checkBoxEnableAP.Checked = demodulator.lft8apon; comboBoxnDepth.SelectedIndex = demodulator.ndepth - 1; #if DEBUG /* demonstrate how to use a native C++ dll to process ** incoming audio. Processing does not affect decoding. This is useful if you want to ** multi-instance XDft.Demodulator. Only one of XDft.Demodulator ** can call GetSignalSpectrum. The AudioProcessor interface can be instanced ** for multiple decodes concurrently and you can, for example, compute ** a spectrum in this processor .*/ IntPtr ip = XDft8RxAudioProcess.RxAudio.GetAudioProcessor(); demodulator.SetAudioSamplesCallback(new XDft.AudioCallback(SamplesCallback), 1000, 512, ip); #endif }