From f3313cc78e637ec9bc11efce5eb943434da93416 Mon Sep 17 00:00:00 2001 From: "Tim E. Real" Date: Mon, 3 Oct 2011 01:56:34 +0000 Subject: Fixed HUGE massive memory leaks in all things using CItemList, and SndFile, dssi, fluidsynth and other huge leaks. Large song with several dssi, vst, fluidsynths leaked 100's of MB, now only ~2MB. --- muse2/ChangeLog | 6 + muse2/muse/app.cpp | 10 +- muse2/muse/arranger/pcanvas.cpp | 8 +- muse2/muse/arranger/pcanvas.h | 1 + muse2/muse/audiotrack.cpp | 3 + muse2/muse/driver/alsamidi.cpp | 25 +- muse2/muse/driver/alsamidi.h | 3 +- muse2/muse/dssihost.cpp | 14 +- muse2/muse/dssihost.h | 2 +- muse2/muse/midiedit/dcanvas.cpp | 5 + muse2/muse/midiedit/dcanvas.h | 1 + muse2/muse/midiedit/ecanvas.cpp | 3 +- muse2/muse/osc.cpp | 523 +++++++++------------------------- muse2/muse/osc.h | 98 +------ muse2/muse/part.h | 5 + muse2/muse/plugin.cpp | 17 +- muse2/muse/plugin.h | 1 + muse2/muse/song.cpp | 8 +- muse2/muse/track.cpp | 5 + muse2/muse/track.h | 2 +- muse2/muse/wave.cpp | 4 +- muse2/muse/wave.h | 30 +- muse2/muse/widgets/canvas.cpp | 5 + muse2/muse/widgets/canvas.h | 1 + muse2/muse/widgets/citem.h | 5 + muse2/muse/widgets/scrollscale.cpp | 1 + muse2/muse/widgets/siglabel.cpp | 6 +- muse2/muse/widgets/tools.cpp | 2 +- muse2/muse/widgets/visibletracks.cpp | 2 +- muse2/synti/fluidsynth/fluidsynti.cpp | 11 + 30 files changed, 290 insertions(+), 517 deletions(-) diff --git a/muse2/ChangeLog b/muse2/ChangeLog index 76feeabe..4c45bc99 100644 --- a/muse2/ChangeLog +++ b/muse2/ChangeLog @@ -1,6 +1,12 @@ 02.09.2011: - SigEdit reworked to use two spinboxes, plan on adding Enter/Return detection so the widget will close when Enter/Return is pressed (rj) + - Fixed HUGE massive memory leaks in all things using CItemList, and SndFile, dssi, fluidsynth and other huge leaks. (Tim) + Addition of 'delete' in places hopefully does not introduce any new unforseen instabilities. + Result: A song with 20 wave/midi tracks and several dssi, vst and fluidsynths, which leaked HUNDREDS of megabytes, + now only leaks about 2 megabytes. TODO: Still some funny business with ALSA, and dssi scanning. + Post-fix LEAK SUMMARY: definitely lost: 259,863 bytes in 356 blocks indirectly lost: 611,874 bytes in 22,834 blocks + possibly lost: 180,508 bytes in 5,211 blocks still reachable: 1,061,068 bytes in 10,522 blocks 30.09.2011: - Fixed long-standing problem with themes (Ia Ora / Bespin etc) and MusE button icons. Some themes don't support multiple-pixmap icons. So mute/solo/rec/stereo/thru always showed the same icon. Replaced w single pm icons. (Tim) diff --git a/muse2/muse/app.cpp b/muse2/muse/app.cpp index 9f858bc3..fd024d57 100644 --- a/muse2/muse/app.cpp +++ b/muse2/muse/app.cpp @@ -112,6 +112,7 @@ extern void initMidiSynth(); extern void exitJackAudio(); extern void exitDummyAudio(); extern void exitOSC(); +extern void exitMidiAlsa(); #ifdef HAVE_LASH #include @@ -1562,12 +1563,13 @@ void MusE::closeEvent(QCloseEvent* event) } #endif - // Changed by Tim. p3.3.14 - //SynthIList* sl = song->syntis(); - //for (iSynthI i = sl->begin(); i != sl->end(); ++i) - // delete *i; song->cleanupForQuit(); + // Give midi devices a chance to close first, above in cleanupForQuit. + if(MusEGlobal::debugMsg) + printf("Muse: Exiting ALSA midi\n"); + exitMidiAlsa(); + if(MusEGlobal::debugMsg) printf("Muse: Cleaning up temporary wavefiles + peakfiles\n"); // Cleanup temporary wavefiles + peakfiles used for undo diff --git a/muse2/muse/arranger/pcanvas.cpp b/muse2/muse/arranger/pcanvas.cpp index 0de8d278..5b5f3a6f 100644 --- a/muse2/muse/arranger/pcanvas.cpp +++ b/muse2/muse/arranger/pcanvas.cpp @@ -112,6 +112,11 @@ PartCanvas::PartCanvas(int* r, QWidget* parent, int sx, int sy) partsChanged(); } +PartCanvas::~PartCanvas() +{ + //items.clearDelete(); +} + //--------------------------------------------------------- // y2pitch //--------------------------------------------------------- @@ -427,7 +432,8 @@ QPoint PartCanvas::raster(const QPoint& p) const void PartCanvas::partsChanged() { - items.clear(); + //items.clear(); + items.clearDelete(); for (iTrack t = tracks->begin(); t != tracks->end(); ++t) { PartList* pl = (*t)->parts(); for (iPart i = pl->begin(); i != pl->end(); ++i) { diff --git a/muse2/muse/arranger/pcanvas.h b/muse2/muse/arranger/pcanvas.h index 3e320e56..e0c601fe 100644 --- a/muse2/muse/arranger/pcanvas.h +++ b/muse2/muse/arranger/pcanvas.h @@ -171,6 +171,7 @@ class PartCanvas : public MusEWidget::Canvas { CMD_PASTE_DIALOG, CMD_PASTE_CLONE_DIALOG, CMD_INSERT_EMPTYMEAS }; PartCanvas(int* raster, QWidget* parent, int, int); + virtual ~PartCanvas(); void partsChanged(); void cmd(int); public slots: diff --git a/muse2/muse/audiotrack.cpp b/muse2/muse/audiotrack.cpp index 1db8dda3..6426a377 100644 --- a/muse2/muse/audiotrack.cpp +++ b/muse2/muse/audiotrack.cpp @@ -202,6 +202,9 @@ AudioTrack::~AudioTrack() } delete[] outBuffers; + for(iCtrlList i = _controller.begin(); i != _controller.end(); ++i) + delete i->second; + } //--------------------------------------------------------- diff --git a/muse2/muse/driver/alsamidi.cpp b/muse2/muse/driver/alsamidi.cpp index 6395bf2d..8ad9c510 100644 --- a/muse2/muse/driver/alsamidi.cpp +++ b/muse2/muse/driver/alsamidi.cpp @@ -3,7 +3,7 @@ // Linux Music Editor // $Id: alsamidi.cpp,v 1.8.2.7 2009/11/19 04:20:33 terminator356 Exp $ // (C) Copyright 2000-2001 Werner Schweer (ws@seh.de) -// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -42,7 +42,7 @@ static int alsaSeqFdi = -1; static int alsaSeqFdo = -1; -snd_seq_t* alsaSeq; +snd_seq_t* alsaSeq = 0; static snd_seq_addr_t musePort; //--------------------------------------------------------- @@ -795,6 +795,27 @@ bool initMidiAlsa() return false; } +namespace MusEApp { + +//--------------------------------------------------------- +// exitMidiAlsa +//--------------------------------------------------------- + +void exitMidiAlsa() +{ + if(alsaSeq) + { + int error = snd_seq_close(alsaSeq); // FIXME Hm, this did not get rid of a buch of valgrind leaks. + if(error < 0) + { + fprintf(stderr, "Could not close ALSA sequencer: %s\n", snd_strerror(error)); + } + } +} + +} // namespace MusEApp + + struct AlsaPort { snd_seq_addr_t adr; char* name; diff --git a/muse2/muse/driver/alsamidi.h b/muse2/muse/driver/alsamidi.h index 13e07ca4..9badd7c4 100644 --- a/muse2/muse/driver/alsamidi.h +++ b/muse2/muse/driver/alsamidi.h @@ -3,7 +3,7 @@ // Linux Music Editor // $Id: alsamidi.h,v 1.2 2004/01/14 09:06:43 wschweer Exp $ // (C) Copyright 2001 Werner Schweer (ws@seh.de) -// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -77,6 +77,7 @@ class MidiAlsaDevice : public MidiDevice { }; extern bool initMidiAlsa(); +extern bool exitMidiAlsa(); extern int alsaSelectRfd(); extern int alsaSelectWfd(); extern void alsaProcessMidiInput(); diff --git a/muse2/muse/dssihost.cpp b/muse2/muse/dssihost.cpp index 42653a91..ad4b2401 100644 --- a/muse2/muse/dssihost.cpp +++ b/muse2/muse/dssihost.cpp @@ -4,7 +4,7 @@ // $Id: dssihost.cpp,v 1.15.2.16 2009/12/15 03:39:58 terminator356 Exp $ // // Copyright (C) 1999-2011 by Werner Schweer and others -// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License @@ -84,8 +84,6 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument { const DSSI_Descriptor* descr; - // CRAPPY PLUGIN ALERT: - // Out of many plugins, with several, Valgrind says something in here is allocated with new. descr = dssi(i); if (descr == 0) break; @@ -120,8 +118,10 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument break; } if(is != synthis.end()) + { + //delete descr; continue; - + } DssiSynth* s = new DssiSynth(fi, descr); if(MusEGlobal::debugMsg) @@ -149,6 +149,9 @@ static void scanDSSILib(QFileInfo& fi) // ddskrjo removed const for argument synthis.push_back(s); } + //else + // delete descr; + } } dlclose(handle); @@ -270,7 +273,8 @@ DssiSynth::DssiSynth(QFileInfo& fi, const DSSI_Descriptor* d) : // ddskrjo remov DssiSynth::~DssiSynth() { - + if(dssi) + delete dssi; } //--------------------------------------------------------- diff --git a/muse2/muse/dssihost.h b/muse2/muse/dssihost.h index cea46e69..05e3b91c 100644 --- a/muse2/muse/dssihost.h +++ b/muse2/muse/dssihost.h @@ -4,7 +4,7 @@ // $Id: dssihost.h,v 1.10.2.7 2009/12/06 10:05:00 terminator356 Exp $ // // Copyright (C) 1999-2011 by Werner Schweer and others -// (C) Copyright 2011 Tim E. Real (terminator356 on users dot sourceforge dot net) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License diff --git a/muse2/muse/midiedit/dcanvas.cpp b/muse2/muse/midiedit/dcanvas.cpp index 3f80133a..138511d6 100644 --- a/muse2/muse/midiedit/dcanvas.cpp +++ b/muse2/muse/midiedit/dcanvas.cpp @@ -111,6 +111,11 @@ DrumCanvas::DrumCanvas(MidiEditor* pr, QWidget* parent, int sx, connect(song, SIGNAL(midiNote(int, int)), SLOT(midiNote(int,int))); } +DrumCanvas::~DrumCanvas() +{ + //items.clearDelete(); +} + //--------------------------------------------------------- // moveCanvasItems //--------------------------------------------------------- diff --git a/muse2/muse/midiedit/dcanvas.h b/muse2/muse/midiedit/dcanvas.h index c25f71ca..c5c51310 100644 --- a/muse2/muse/midiedit/dcanvas.h +++ b/muse2/muse/midiedit/dcanvas.h @@ -114,6 +114,7 @@ class DrumCanvas : public EventCanvas { }; DrumCanvas(MidiEditor*, QWidget*, int, int, const char* name = 0); + virtual ~DrumCanvas(); void cmd(int); virtual void modifySelected(MusEWidget::NoteInfo::ValType type, int delta); virtual void keyPress(QKeyEvent* event); diff --git a/muse2/muse/midiedit/ecanvas.cpp b/muse2/muse/midiedit/ecanvas.cpp index cb96118f..b30574f1 100644 --- a/muse2/muse/midiedit/ecanvas.cpp +++ b/muse2/muse/midiedit/ecanvas.cpp @@ -147,7 +147,8 @@ void EventCanvas::songChanged(int flags) return; if (flags & ~SC_SELECTION) { - items.clear(); + //items.clear(); + items.clearDelete(); start_tick = MAXINT; end_tick = 0; curPart = 0; diff --git a/muse2/muse/osc.cpp b/muse2/muse/osc.cpp index e7aaa46b..c0d936ec 100644 --- a/muse2/muse/osc.cpp +++ b/muse2/muse/osc.cpp @@ -4,7 +4,7 @@ // $Id: osc.cpp,v 1.0.0.0 2010/04/22 03:39:58 terminator356 Exp $ // // Copyright (C) 1999-2011 by Werner Schweer and others -// OSC module added by Tim. +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License @@ -28,21 +28,23 @@ // Turn on debugging messages //#define OSC_DEBUG +// Whether to use a QProcess or fork + execlp to start the gui. (Note fork + execlp give problems - zombies when synth window closed.) +#define _USE_QPROCESS_FOR_GUI_ 1 + #include -//#include -//#include #include -#include -#include -//#include -//#include -#include #include #include #include -#include -#include + +#ifdef _USE_QPROCESS_FOR_GUI_ + #include +#else + #include + #include + #include +#endif #include @@ -55,23 +57,11 @@ #include "track.h" #include "song.h" #include "synth.h" -//#include "audio.h" -//#include "jackaudio.h" -//#include "midi.h" -//#include "midiport.h" -//#include "al/al.h" -//#include "al/xml.h" -//#include "xml.h" -//#include "midictrl.h" -//#include "ladspaplugin.h" - #include "app.h" #include "globals.h" #include "globaldefs.h" -//#include "al/dsp.h" static lo_server_thread serverThread = 0; -///static char osc_path_tmp[1024]; static char* url = 0; static bool oscServerRunning = false; @@ -107,7 +97,6 @@ static int oscDebugHandler(const char* path, const char* types, lo_arg** argv, int oscMessageHandler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data) - //int argc, lo_message data, void* user_data) { const char* p = path; @@ -409,61 +398,6 @@ void stopOSC() } // namespace MusEApp -/* -//--------------------------------------------------------- -// OscControlFifo -// put -// return true on fifo overflow -//--------------------------------------------------------- - -bool OscControlFifo::put(const OscControlValue& event) - { - if (size < OSC_FIFO_SIZE) { - fifo[wIndex] = event; - wIndex = (wIndex + 1) % OSC_FIFO_SIZE; - // q_atomic_increment(&size); - ++size; - return false; - } - return true; - } - -//--------------------------------------------------------- -// get -//--------------------------------------------------------- - -OscControlValue OscControlFifo::get() - { - OscControlValue event(fifo[rIndex]); - rIndex = (rIndex + 1) % OSC_FIFO_SIZE; - // q_atomic_decrement(&size); - --size; - return event; - } - -//--------------------------------------------------------- -// peek -//--------------------------------------------------------- - -const OscControlValue& OscControlFifo::peek(int n) - { - int idx = (rIndex + n) % OSC_FIFO_SIZE; - return fifo[idx]; - } - -//--------------------------------------------------------- -// remove -//--------------------------------------------------------- - -void OscControlFifo::remove() - { - rIndex = (rIndex + 1) % OSC_FIFO_SIZE; - // q_atomic_decrement(&size); - --size; - } -*/ - - //--------------------------------------------------------- // OscIF // Open Sound Control Interface @@ -471,12 +405,6 @@ void OscControlFifo::remove() OscIF::OscIF() { - //_oscPluginI = 0; - - //#ifdef DSSI_SUPPORT - //_oscSynthIF = 0; - //#endif - _uiOscTarget = 0; _uiOscSampleRatePath = 0; _uiOscShowPath = 0; @@ -484,17 +412,17 @@ OscIF::OscIF() _uiOscConfigurePath = 0; _uiOscProgramPath = 0; _uiOscPath = 0; - //guiPid = -1; +#ifdef _USE_QPROCESS_FOR_GUI_ _oscGuiQProc = 0; +#else + _guiPid = -1; +#endif _oscGuiVisible = false; - - //_oscControlFifos = 0; } OscIF::~OscIF() { - //if (guiPid != -1) - // kill(guiPid, SIGHUP); +#ifdef _USE_QPROCESS_FOR_GUI_ if(_oscGuiQProc) { if(_oscGuiQProc->state()) @@ -516,10 +444,20 @@ OscIF::~OscIF() // so kill is not desirable. // We could wait until terminate finished but don't think that's good here. ///QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); + _oscGuiQProc->waitForFinished(3000); } - //delete _oscGuiQProc; + delete _oscGuiQProc; } - + +#else // NOT _USE_QPROCESS_FOR_GUI_ + + if (_guiPid != -1) + { + if(kill(_guiPid, SIGHUP) != -1) + _guiPid = -1; + } +#endif // _USE_QPROCESS_FOR_GUI_ + if(_uiOscTarget) lo_address_free(_uiOscTarget); if(_uiOscSampleRatePath) @@ -534,23 +472,7 @@ OscIF::~OscIF() free(_uiOscProgramPath); if(_uiOscPath) free(_uiOscPath); - - //if(_oscControlFifos) - // delete[] _oscControlFifos; -} - -/* -//--------------------------------------------------------- -// oscFifo -//--------------------------------------------------------- - -OscControlFifo* OscIF::oscFifo(unsigned long i) const -{ - if(!_oscControlFifos) - return 0; - return &_oscControlFifos[i]; } -*/ //--------------------------------------------------------- // oscUpdate @@ -709,6 +631,9 @@ int OscIF::oscExiting(lo_arg**) // The gui is gone now, right? _oscGuiVisible = false; +// Just an attempt to really kill the process, an attempt to fix gui not re-showing after closing. Doesn't help. +/* +#ifdef _USE_QPROCESS_FOR_GUI_ if(_oscGuiQProc) { if(_oscGuiQProc->state()) @@ -730,10 +655,34 @@ int OscIF::oscExiting(lo_arg**) // so kill is not desirable. // We could wait until terminate finished but don't think that's good here. ///QTimer::singleShot( 5000, _oscGuiQProc, SLOT( kill() ) ); + _oscGuiQProc->waitForFinished(3000); } //delete _oscGuiQProc; + //_oscGuiQProc = 0; } - + + +#else // NOT _USE_QPROCESS_FOR_GUI_ + + if(_guiPid != -1) + { + #ifdef OSC_DEBUG + printf("OscIF::oscExiting hanging up _guiPid:%d\n", _guiPid); + #endif + //if(kill(_guiPid, SIGHUP) != -1) + //if(kill(_guiPid, SIGTERM) != -1) + if(kill(_guiPid, SIGKILL) != -1) + { + #ifdef OSC_DEBUG + printf(" hang up sent\n"); + #endif + _guiPid = -1; + } + } + +#endif // _USE_QPROCESS_FOR_GUI_ +*/ + if(_uiOscTarget) lo_address_free(_uiOscTarget); _uiOscTarget = 0; @@ -756,9 +705,6 @@ int OscIF::oscExiting(lo_arg**) free(_uiOscPath); _uiOscPath = 0; - //if(_oscControlFifos) - // delete[] _oscControlFifos; - //const DSSI_Descriptor* dssi = synth->dssi; //const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin; //if(ld->deactivate) @@ -851,14 +797,22 @@ void OscIF::oscSendConfigure(const char *key, const char *val) // oscInitGui //--------------------------------------------------------- -//bool OscIF::oscInitGui() bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QString& name, const QString& label, const QString& filePath, const QString& guiPath) { // Are we already running? We don't want to allow another process do we... +#ifdef _USE_QPROCESS_FOR_GUI_ if((_oscGuiQProc != 0) && (_oscGuiQProc->state())) return true; +#else + if(_guiPid != -1) + return true; +#endif + #ifdef OSC_DEBUG + fprintf(stderr, "OscIF::oscInitGui\n"); + #endif + if(!url) { fprintf(stderr, "OscIF::oscInitGui no server url!\n"); @@ -871,198 +825,83 @@ bool OscIF::oscInitGui(const QString& typ, const QString& baseName, const QStrin return false; } - // - // start gui - // - //static char oscUrl[1024]; - //char oscUrl[1024]; QString oscUrl; - - //snprintf(oscUrl, 1024, "%s/%s/%s", url, baseName.ascii(), name.ascii()); - //snprintf(oscUrl, 1024, "%s%s/%s/%s", url, typ.toLatin1().constData(), baseName.toLatin1().constData(), name.toLatin1().constData()); - //oscUrl = QString("%1%2/%3/%4").arg(QString(QT_TRANSLATE_NOOP("@default", url))).arg(typ).arg(baseName).arg(name); oscUrl = QString("%1%2/%3/%4").arg(QString(QT_TRANSLATE_NOOP("@default", url))).arg(typ).arg(baseName).arg(label); - // Removed p4.0.19 Tim - /* - //QString guiPath(info.path() + "/" + info.baseName()); - //QString guiPath(synth->info.dirPath() + "/" + synth->info.baseName()); - QString guiPath(dirPath + "/" + baseName); + +#ifdef _USE_QPROCESS_FOR_GUI_ + + // fork + execlp cause the process to remain (zombie) after closing gui, requiring manual kill. + // Using QProcess works OK. + // No QProcess created yet? Do it now. Only once per SynthIF instance. Exists until parent destroyed. + if(_oscGuiQProc == 0) + //_oscGuiQProc = new QProcess(muse); + _oscGuiQProc = new QProcess(); + + QString program(guiPath); + QStringList arguments; + arguments << oscUrl + << filePath + << name + << QString("channel-1"); #ifdef OSC_DEBUG - fprintf(stderr, "OscIF::oscInitGui guiPath:%s\n", guiPath.toLatin1().constData()); + fprintf(stderr, "OscIF::oscInitGui starting QProcess\n"); #endif - - QDir guiDir(guiPath, "*", QDir::Unsorted, QDir::Files); - if (guiDir.exists()) + _oscGuiQProc->start(program, arguments); + + if(_oscGuiQProc->state()) { - //const QFileInfoList list = guiDir.entryInfoList(); - QStringList list = guiDir.entryList(); - - //for (int i = 0; i < list.size(); ++i) { - for (int i = 0; i < list.count(); ++i) - { - - //QFileInfo fi = list.at(i); - QFileInfo fi(guiPath + QString("/") + list[i]); - - QString gui(fi.filePath()); - if (gui.contains('_') == 0) - continue; - struct stat buf; - - //if (stat(gui.toAscii().data(), &buf)) { - if (stat(gui.toLatin1().constData(), &buf)) { - - perror("stat failed"); - continue; - } - - #ifdef OSC_DEBUG - fprintf(stderr, "OscIF::oscInitGui %s %s %s %s\n", - //fi.filePath().toAscii().data(), - //fi.fileName().toAscii().data(), - fi.filePath().toLatin1().constData(), - //fi.fileName().ascii(), - - oscUrl.toLatin1().constData(), - - //synth->info.filePath().ascii(), - filePath.toLatin1().constData(), - - //name().toAscii().data(), - //synth->name().ascii()); - name.toLatin1().constData()); - #endif - */ - - //if ((S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) && - // (buf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) - //{ - - // Changed by T356. - // fork + execlp were causing the processes to remain after closing gui, requiring manual kill. - // Changed to QProcess, works OK now. - //if((guiPid = fork()) == 0) - //{ - // No QProcess created yet? Do it now. Only once per SynthIF instance. Exists until parent destroyed. - if(_oscGuiQProc == 0) - //_oscGuiQProc = new QProcess(muse); - _oscGuiQProc = new QProcess(); - - //QString program(fi.filePath()); - QString program(guiPath); - QStringList arguments; - arguments << oscUrl - << filePath - << name - << QString("channel-1"); - - /* - fprintf(stderr, "OscIF::oscInitGui %s %s %s %s\n", - //fi.filePath().toAscii().data(), - //fi.fileName().toAscii().data(), - guiPath.toLatin1().constData(), - //fi.fileName().ascii(), - - oscUrl.toLatin1().constData(), - - //synth->info.filePath().ascii(), - filePath.toLatin1().constData(), - - //name().toAscii().data(), - //synth->name().ascii()); - name.toLatin1().constData()); - */ - - /* Leave out Qt3 stuff for reference - Orcan: - // Don't forget this, he he... - _oscGuiQProc->clearArguments(); - - _oscGuiQProc->addArgument(fi.filePath()); - //_oscGuiQProc->addArgument(fi.fileName()); // No conventional 'Arg0' here. - //_oscGuiQProc->addArgument(QString(oscUrl)); - _oscGuiQProc->addArgument(oscUrl); - //_oscGuiQProc->addArgument(synth->info.filePath()); - _oscGuiQProc->addArgument(filePath); - //_oscGuiQProc->addArgument(synth->name()); - _oscGuiQProc->addArgument(name); - _oscGuiQProc->addArgument(QString("channel-1")); - */ - #ifdef OSC_DEBUG - fprintf(stderr, "OscIF::oscInitGui starting QProcess\n"); - #endif - _oscGuiQProc->start(program, arguments); - - - if(_oscGuiQProc->state()) - { - #ifdef OSC_DEBUG - fprintf(stderr, "OscIF::oscInitGui started QProcess\n"); - #endif - - //guiPid = _oscGuiQProc->processIdentifier(); - } - else - { - - /* - execlp( - //fi.filePath().toAscii().data(), - //fi.fileName().toAscii().data(), - fi.filePath().ascii(), - fi.fileName().ascii(), - - oscUrl, - - //info.filePath().toAscii().data(), - //name().toAscii().data(), - synth->info.filePath().ascii(), - synth->name().ascii(), - - "channel 1", (void*)0); - */ - - fprintf(stderr, "exec %s %s %s failed: %s\n", - //fi.filePath().toAscii().data(), - //fi.fileName().toAscii().data(), - //fi.filePath().toLatin1().constData(), - guiPath.toLatin1().constData(), - //fi.fileName().toLatin1().constData(), - - oscUrl.toLatin1().constData(), - - //name().toAscii().data(), - //synth->name().ascii(), - name.toLatin1().constData(), - - strerror(errno)); - - // It's Ok, Keep going. So nothing happens. So what. The timeout in showGui will just leave. - // Maybe it's a 'busy' issue somewhere - allow to try again later + save work now. - //exit(1); + #ifdef OSC_DEBUG + fprintf(stderr, "OscIF::oscInitGui started QProcess\n"); + #endif + } + else + { + fprintf(stderr, "exec %s %s %s %s failed: %s\n", + guiPath.toLatin1().constData(), + oscUrl.toLatin1().constData(), + filePath.toLatin1().constData(), + name.toLatin1().constData(), + strerror(errno)); + //exit(1); + } + + #ifdef OSC_DEBUG + fprintf(stderr, "OscIF::oscInitGui after QProcess\n"); + #endif + +#else // NOT _USE_QPROCESS_FOR_GUI_ - } - - #ifdef OSC_DEBUG - fprintf(stderr, "OscIF::oscInitGui after QProcess\n"); - #endif - //} - //} - //} - //synth->_hasGui = true; - /* + #ifdef OSC_DEBUG + fprintf(stderr, "forking...\n"); + #endif + + QString guiName = QFileInfo(guiPath).fileName(); + // Note: fork + execlp cause the process to remain (zombie) after closing gui, requiring manual kill. Use QProcess instead. + if((_guiPid = fork()) == 0) + { + execlp( + guiPath.toLatin1().constData(), + guiName.toLatin1().constData(), + oscUrl.toLatin1().constData(), + filePath.toLatin1().constData(), + name.toLatin1().constData(), + "channel 1", (void*)0); + + // Should not return after execlp. If so it's an error. + fprintf(stderr, "exec %s %s %s %s %s failed: %s\n", + guiPath.toLatin1().constData(), + guiName.toLatin1().constData(), + oscUrl.toLatin1().constData(), + filePath.toLatin1().constData(), + name.toLatin1().constData(), + strerror(errno)); + //exit(1); } - else { - printf("OscIF::oscInitGui %s: no dir for gui found: %s\n", - //name().toAscii().data(), guiPath.toAscii().data()); - //synth->name().ascii(), guiPath.ascii()); - name.toLatin1().constData(), guiPath.toLatin1().constData()); - - //synth->_hasGui = false; - } - */ - + +#endif // _USE_QPROCESS_FOR_GUI_ + return true; } @@ -1080,8 +919,11 @@ void OscIF::oscShowGui(bool v) if (v == oscGuiVisible()) return; - //if(guiPid == -1) +#ifdef _USE_QPROCESS_FOR_GUI_ if((_oscGuiQProc == 0) || (!_oscGuiQProc->state())) +#else + if(_guiPid == -1) +#endif { // We need an indicator that update was called - update must have been called to get new path etc... // If the process is not running this path is invalid, right? @@ -1138,19 +980,9 @@ bool OscIF::oscGuiVisible() const // oscSetSynthIF //--------------------------------------------------------- -//void OscIF::oscSetSynthIF(DssiSynthIF* s) void OscDssiIF::oscSetSynthIF(DssiSynthIF* s) { _oscSynthIF = s; - //if(_oscControlFifos) - // delete[] _oscControlFifos; - //_oscControlFifos = 0; - - //if(_oscSynthIF && _oscSynthIF->dssiSynth()) - //{ - // unsigned long ports = _oscSynthIF->dssiSynth()->inControls(); - // _oscControlFifos = new OscControlFifo[ports]; - //} } //--------------------------------------------------------- @@ -1172,58 +1004,6 @@ int OscDssiIF::oscUpdate(lo_arg **argv) if(_oscSynthIF) _oscSynthIF->oscUpdate(); - /* - if(_oscSynthIF) - { - // Send current string configuration parameters. - StringParamMap& map = _oscSynthIF->dssiSynthI()->stringParameters(); - int i = 0; - for(ciStringParamMap r = map.begin(); r != map.end(); ++r) - { - lo_send(_uiOscTarget, _uiOscConfigurePath, "ss", r->first.c_str(), r->second.c_str()); - // Avoid overloading the GUI if there are lots and lots of params. - if((i+1) % 50 == 0) - usleep(300000); - ++i; - } - - // Send current bank and program. - unsigned long bank, prog; - _oscSynthIF->dssiSynthI()->currentProg(&prog, &bank, 0); - lo_send(_uiOscTarget, _uiOscProgramPath, "ii", bank, prog); - - // Send current control values. - unsigned long ports = _oscSynthIF->dssiSynth()->inControls(); - for(unsigned long i = 0; i < ports; ++i) - { - unsigned long k = _oscSynthIF->dssiSynth()->inControlPortIdx(i); - lo_send(_uiOscTarget, _uiOscControlPath, "if", k, _oscSynthIF->getParameter(i)); - // Avoid overloading the GUI if there are lots and lots of ports. - if((i+1) % 50 == 0) - usleep(300000); - } - } - */ - - /* - char uiOscGuiPath[strlen(_uiOscPath)+6]; - sprintf(uiOscGuiPath, "%s/%s", _uiOscPath, "show"); - - #ifdef OSC_DEBUG - printf("OscIF::oscUpdate Sending show uiOscGuiPath:%s\n", uiOscGuiPath); - #endif - - lo_send(_uiOscTarget, uiOscGuiPath, ""); - - sprintf(uiOscGuiPath, "%s/%s", _uiOscPath, "hide"); - - #ifdef OSC_DEBUG - printf("OscIF::oscUpdate Sending hide uiOscGuiPath:%s\n", uiOscGuiPath); - #endif - - lo_send(_uiOscTarget, uiOscGuiPath, ""); - */ - #if 0 /* Send current bank/program (-FIX- another race...) */ if (instance->pendingProgramChange < 0) { @@ -1256,8 +1036,6 @@ int OscDssiIF::oscUpdate(lo_arg **argv) int OscDssiIF::oscConfigure(lo_arg** argv) { - //OscIF::oscConfigure(argv); - if(_oscSynthIF) _oscSynthIF->oscConfigure((const char*)&argv[0]->s, (const char*)&argv[1]->s); return 0; @@ -1269,8 +1047,6 @@ int OscDssiIF::oscConfigure(lo_arg** argv) int OscDssiIF::oscMidi(lo_arg** argv) { - //OscIF::oscMidi(argv); - if(_oscSynthIF) _oscSynthIF->oscMidi(argv[0]->m[1], argv[0]->m[2], argv[0]->m[3]); @@ -1283,8 +1059,6 @@ int OscDssiIF::oscMidi(lo_arg** argv) int OscDssiIF::oscProgram(lo_arg** argv) { - //OscIF::oscProgram(argv); - if(_oscSynthIF) _oscSynthIF->oscProgram(argv[1]->i, argv[0]->i); @@ -1297,8 +1071,6 @@ int OscDssiIF::oscProgram(lo_arg** argv) int OscDssiIF::oscControl(lo_arg** argv) { - //OscIF::oscControl(argv); - int port = argv[0]->i; if(port < 0) return 0; @@ -1319,8 +1091,7 @@ bool OscDssiIF::oscInitGui() return OscIF::oscInitGui(QT_TRANSLATE_NOOP("@default", "dssi_synth"), _oscSynthIF->dssiSynth()->baseName(), _oscSynthIF->dssiSynth()->name(), _oscSynthIF->dssiSynthI()->name(), - //_oscSynthIF->dssiSynth()->filePath(), _oscSynthIF->dssiSynth()->path()); - _oscSynthIF->dssiSynth()->fileName(), _oscSynthIF->dssi_ui_filename()); // p4.0.19 + _oscSynthIF->dssiSynth()->fileName(), _oscSynthIF->dssi_ui_filename()); } #endif // DSSI_SUPPORT @@ -1334,15 +1105,6 @@ bool OscDssiIF::oscInitGui() void OscEffectIF::oscSetPluginI(PluginI* s) { _oscPluginI = s; - //if(_oscControlFifos) - // delete[] _oscControlFifos; - //_oscControlFifos = 0; - - //if(_oscPluginI && _oscPluginI->plugin()) - //{ - // unsigned long ports = _oscPluginI->plugin()->controlInPorts(); - // _oscControlFifos = new OscControlFifo[ports]; - //} } //--------------------------------------------------------- @@ -1370,8 +1132,6 @@ int OscEffectIF::oscUpdate(lo_arg** argv) int OscEffectIF::oscConfigure(lo_arg** argv) { - //OscIF::oscConfigure(argv); - if(_oscPluginI) _oscPluginI->oscConfigure((const char*)&argv[0]->s, (const char*)&argv[1]->s); @@ -1384,8 +1144,6 @@ int OscEffectIF::oscConfigure(lo_arg** argv) int OscEffectIF::oscControl(lo_arg** argv) { - //OscIF::oscControl(argv); - int port = argv[0]->i; if(port < 0) return 0; @@ -1406,8 +1164,7 @@ bool OscEffectIF::oscInitGui() return OscIF::oscInitGui(QT_TRANSLATE_NOOP("@default", "ladspa_efx"), _oscPluginI->plugin()->lib(false), _oscPluginI->plugin()->label(), _oscPluginI->label(), - //_oscPluginI->plugin()->filePath(), _oscPluginI->plugin()->dirPath(false)); - _oscPluginI->plugin()->fileName(), _oscPluginI->dssi_ui_filename()); // p4.0.19 + _oscPluginI->plugin()->fileName(), _oscPluginI->dssi_ui_filename()); } diff --git a/muse2/muse/osc.h b/muse2/muse/osc.h index a0973ac7..8b6ba746 100644 --- a/muse2/muse/osc.h +++ b/muse2/muse/osc.h @@ -4,6 +4,7 @@ // $Id: osc.h,v 1.0.0.0 2010/04/22 10:05:00 terminator356 Exp $ // // Copyright (C) 1999-2011 by Werner Schweer and others +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License @@ -36,101 +37,10 @@ class QString; class PluginI; class OscIF; -/* -// Keep the OSC fifo small. There may be thousands of controls, and each control needs a fifo. -// Oops, no, if the user keeps adjusting a slider without releasing the mouse button, then all of the -// events are sent at once upon releasing the button, meaning there might be thousands of events at once. -#define OSC_FIFO_SIZE 512 - -//--------------------------------------------------------- -// OscControlValue -// Item struct for OscGuiControlFifo. -//--------------------------------------------------------- - -struct OscControlValue -{ - //int idx; - float value; - int frame; // Added p4.0.15 -}; - -//--------------------------------------------------------- -// OscControlFifo -// A fifo for each of the OSC controls. -//--------------------------------------------------------- - -class OscControlFifo -{ - OscControlValue fifo[OSC_FIFO_SIZE]; - volatile int size; - int wIndex; - int rIndex; - - public: - OscControlFifo() { clear(); } - bool put(const OscControlValue& event); // returns true on fifo overflow - OscControlValue get(); - const OscControlValue& peek(int n = 0); - void remove(); - bool isEmpty() const { return size == 0; } - void clear() { size = 0, wIndex = 0, rIndex = 0; } - int getSize() const { return size; } -}; -*/ - -//--------------------------------------------------------- -// OscIF -// Open Sound Control Interface -//--------------------------------------------------------- - -/* -class OscIF -{ - private: - PluginI* _oscPluginI; - - #ifdef DSSI_SUPPORT - DssiSynthIF* _oscSynthIF; - #endif - - QProcess* _oscGuiQProc; - void* _uiOscTarget; - char* _uiOscShowPath; - char* _uiOscControlPath; - char* _uiOscConfigurePath; - char* _uiOscProgramPath; - char* _uiOscPath; - bool _oscGuiVisible; - - OscControlFifo* _oscControlFifos; - - public: - OscIF(); - ~OscIF(); - - void oscSetPluginI(PluginI*); - - #ifdef DSSI_SUPPORT - void oscSetSynthIF(DssiSynthIF*); - #endif - - int oscUpdate(lo_arg**); - int oscProgram(lo_arg**); - int oscControl(lo_arg**); - int oscExiting(lo_arg**); - int oscMidi(lo_arg**); - int oscConfigure(lo_arg**); - - bool oscInitGui(); - void oscShowGui(bool); - bool oscGuiVisible() const; - OscControlFifo* oscFifo(unsigned long) const; -}; -*/ - class OscIF { protected: + pid_t _guiPid; QProcess* _oscGuiQProc; void* _uiOscTarget; char* _uiOscPath; @@ -141,8 +51,6 @@ class OscIF char* _uiOscShowPath; bool _oscGuiVisible; - //OscControlFifo* _oscControlFifos; - virtual bool oscInitGui(const QString& /*typ*/, const QString& /*baseName*/, const QString& /*name*/, const QString& /*label*/, const QString& /*filePath*/, const QString& /*guiPath*/); @@ -150,8 +58,6 @@ class OscIF OscIF(); virtual ~OscIF(); - //OscControlFifo* oscFifo(unsigned long) const; - virtual int oscUpdate(lo_arg**); virtual int oscProgram(lo_arg**) { return 0; } virtual int oscControl(lo_arg**) { return 0; } diff --git a/muse2/muse/part.h b/muse2/muse/part.h index d5b85b03..7042eedf 100644 --- a/muse2/muse/part.h +++ b/muse2/muse/part.h @@ -169,6 +169,11 @@ class PartList : public std::multimap > { void remove(Part* part); int index(Part*); Part* find(int idx); + void clearDelete() { + for (iPart i = begin(); i != end(); ++i) + delete i->second; + clear(); + } }; extern void chainClone(Part* p); diff --git a/muse2/muse/plugin.cpp b/muse2/muse/plugin.cpp index 53e3d471..7205f482 100644 --- a/muse2/muse/plugin.cpp +++ b/muse2/muse/plugin.cpp @@ -4,6 +4,7 @@ // $Id: plugin.cpp,v 1.21.2.23 2009/12/15 22:07:12 spamatica Exp $ // // (C) Copyright 2000 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -770,6 +771,8 @@ Plugin::~Plugin() { //if(_portDescriptors) // delete[] _portDescriptors; + if(plugin) + delete plugin; } //--------------------------------------------------------- @@ -851,6 +854,8 @@ int Plugin::incReferences(int val) plugin = descr->LADSPA_Plugin; break; } + //else + // delete descr; } } else @@ -881,6 +886,8 @@ int Plugin::incReferences(int val) break; } + //else + // delete descr; } } } @@ -1106,8 +1113,10 @@ static void loadPluginLib(QFileInfo* fi) { // Make sure it doesn't already exist. if(plugins.find(fi->completeBaseName(), QString(descr->LADSPA_Plugin->Label)) != 0) + { + //delete descr; continue; - + } #ifdef PLUGIN_DEBUGIN fprintf(stderr, "loadPluginLib: dssi effect name:%s inPlaceBroken:%d\n", descr->LADSPA_Plugin->Name, LADSPA_IS_INPLACE_BROKEN(descr->LADSPA_Plugin->Properties)); #endif @@ -1120,6 +1129,8 @@ static void loadPluginLib(QFileInfo* fi) plugins.add(fi, descr->LADSPA_Plugin, true); } + //else + // delete descr; } } else @@ -1152,8 +1163,10 @@ static void loadPluginLib(QFileInfo* fi) // Make sure it doesn't already exist. if(plugins.find(fi->completeBaseName(), QString(descr->Label)) != 0) + { + //delete descr; continue; - + } #ifdef PLUGIN_DEBUGIN fprintf(stderr, "loadPluginLib: ladspa effect name:%s inPlaceBroken:%d\n", descr->Name, LADSPA_IS_INPLACE_BROKEN(descr->Properties)); #endif diff --git a/muse2/muse/plugin.h b/muse2/muse/plugin.h index 2a98760e..00144610 100644 --- a/muse2/muse/plugin.h +++ b/muse2/muse/plugin.h @@ -4,6 +4,7 @@ // $Id: plugin.h,v 1.9.2.13 2009/12/06 01:25:21 terminator356 Exp $ // // (C) Copyright 2000 Werner Schweer (ws@seh.de) +// (C) Copyright 2011 Tim E. Real (terminator356 on sourceforge) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License diff --git a/muse2/muse/song.cpp b/muse2/muse/song.cpp index 6a43e457..a994b0e6 100644 --- a/muse2/muse/song.cpp +++ b/muse2/muse/song.cpp @@ -2341,6 +2341,8 @@ void Song::cleanupForQuit() printf("deleting midi devices except synths\n"); for(iMidiDevice imd = midiDevices.begin(); imd != midiDevices.end(); ++imd) { + // Close the device. Handy to do all devices here, including synths. + (*imd)->close(); // Since Syntis are midi devices, there's no need to delete them below. if((*imd)->isSynti()) continue; @@ -2373,11 +2375,15 @@ void Song::cleanupForQuit() continue; delete (*imi); } - midiInstruments.clear(); // midi devices + midiInstruments.clear(); // midi instruments // Nothing required for ladspa plugin list, and rack instances of them // are handled by ~AudioTrack. + if(MusEGlobal::debugMsg) + printf("Muse: Deleting sound files\n"); + SndFile::sndFiles.clearDelete(); + if(MusEGlobal::debugMsg) printf("...finished cleaning up.\n"); } diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp index 57c4a658..18578d88 100644 --- a/muse2/muse/track.cpp +++ b/muse2/muse/track.cpp @@ -252,6 +252,11 @@ Track::Track(const Track& t, bool cloneParts) } } +Track::~Track() +{ + _parts.clearDelete(); +} + //--------------------------------------------------------- // operator = // Added by Tim. Parts' track members MUST point to this track, diff --git a/muse2/muse/track.h b/muse2/muse/track.h index 9c6aea24..f0f8ebde 100644 --- a/muse2/muse/track.h +++ b/muse2/muse/track.h @@ -104,7 +104,7 @@ class Track { Track(TrackType); //Track(const Track&); Track(const Track&, bool cloneParts); - virtual ~Track() {}; + virtual ~Track(); virtual Track& operator=(const Track& t); static const char* _cname[]; diff --git a/muse2/muse/wave.cpp b/muse2/muse/wave.cpp index 731606d3..e9fa64d2 100644 --- a/muse2/muse/wave.cpp +++ b/muse2/muse/wave.cpp @@ -90,7 +90,7 @@ SndFile::~SndFile() delete finfo; if (cache) { for (unsigned i = 0; i < channels(); ++i) - delete cache[i]; + delete [] cache[i]; delete[] cache; cache = 0; } @@ -150,7 +150,7 @@ void SndFile::readCache(const QString& path, bool showProgress) if (cache) { for (unsigned i = 0; i < channels(); ++i) - delete cache[i]; + delete [] cache[i]; delete[] cache; } if (samples() == 0) { diff --git a/muse2/muse/wave.h b/muse2/muse/wave.h index 2f97e6c5..231ed7dc 100644 --- a/muse2/muse/wave.h +++ b/muse2/muse/wave.h @@ -42,18 +42,7 @@ struct SampleV { unsigned char rms; }; -//--------------------------------------------------------- -// SndFileList -//--------------------------------------------------------- - -class SndFile; -class SndFileList : public std::list { - public: - SndFile* search(const QString& name); - }; - -typedef SndFileList::iterator iSndFile; -typedef SndFileList::const_iterator ciSndFile; +class SndFileList; //--------------------------------------------------------- // SndFile @@ -183,6 +172,23 @@ class SndFileR { }; +//--------------------------------------------------------- +// SndFileList +//--------------------------------------------------------- + +class SndFileList : public std::list { + public: + SndFile* search(const QString& name); + void clearDelete() { + for (SndFileList::iterator i = begin(); i != end(); ++i) + delete *i; + clear(); + } + }; + +typedef SndFileList::iterator iSndFile; +typedef SndFileList::const_iterator ciSndFile; + #if 0 class Clip; diff --git a/muse2/muse/widgets/canvas.cpp b/muse2/muse/widgets/canvas.cpp index c498bfd1..811561e3 100644 --- a/muse2/muse/widgets/canvas.cpp +++ b/muse2/muse/widgets/canvas.cpp @@ -82,6 +82,11 @@ Canvas::Canvas(QWidget* parent, int sx, int sy, const char* name) connect(song, SIGNAL(posChanged(int, unsigned, bool)), this, SLOT(setPos(int, unsigned, bool))); } +Canvas::~Canvas() +{ + items.clearDelete(); +} + //--------------------------------------------------------- // setPos // set one of three markers diff --git a/muse2/muse/widgets/canvas.h b/muse2/muse/widgets/canvas.h index 553ef407..954b865d 100644 --- a/muse2/muse/widgets/canvas.h +++ b/muse2/muse/widgets/canvas.h @@ -190,6 +190,7 @@ class Canvas : public View { void horizontalZoomOut(); public: Canvas(QWidget* parent, int sx, int sy, const char* name = 0); + virtual ~Canvas(); bool isSingleSelection(); int selectionSize(); Tool tool() const { return _tool; } diff --git a/muse2/muse/widgets/citem.h b/muse2/muse/widgets/citem.h index bdeca213..e2ddd8a0 100644 --- a/muse2/muse/widgets/citem.h +++ b/muse2/muse/widgets/citem.h @@ -101,6 +101,11 @@ class CItemList: public std::multimap > { public: void add(CItem*); CItem* find(const QPoint& pos) const; + void clearDelete() { + for (iCItem i = begin(); i != end(); ++i) + delete i->second; + clear(); + } }; } // namespace MusEWidget diff --git a/muse2/muse/widgets/scrollscale.cpp b/muse2/muse/widgets/scrollscale.cpp index e7d40f67..572a1d86 100644 --- a/muse2/muse/widgets/scrollscale.cpp +++ b/muse2/muse/widgets/scrollscale.cpp @@ -224,6 +224,7 @@ ScrollScale::ScrollScale ( int s1, int s2, int cs, int max_, Qt::Orientation o, down = 0; logbase = bas; invers = inv; + scaleVal = 0; double min, max; if ( scaleMin < 0 ) diff --git a/muse2/muse/widgets/siglabel.cpp b/muse2/muse/widgets/siglabel.cpp index 9916bd0a..f571c2f1 100644 --- a/muse2/muse/widgets/siglabel.cpp +++ b/muse2/muse/widgets/siglabel.cpp @@ -43,12 +43,12 @@ namespace MusEWidget { // edit Signature Values (4/4) //--------------------------------------------------------- -SigLabel::SigLabel(int z, int n, QWidget* parent) : QLabel(parent) +SigLabel::SigLabel(int zz, int nn, QWidget* parent) : QLabel(parent) { - z = n = 0; + z = n = 0; setFocusPolicy(Qt::NoFocus); setAlignment(Qt::AlignCenter); - setValue(z, n); + setValue(zz, nn); } SigLabel::SigLabel(const AL::TimeSignature& sig, QWidget* parent) : QLabel(parent) diff --git a/muse2/muse/widgets/tools.cpp b/muse2/muse/widgets/tools.cpp index ccd0f89b..113de6c4 100644 --- a/muse2/muse/widgets/tools.cpp +++ b/muse2/muse/widgets/tools.cpp @@ -129,7 +129,7 @@ void EditToolBar::toolChanged(QAction* action) EditToolBar::~EditToolBar() { - delete actions; + delete [] actions; } //--------------------------------------------------------- diff --git a/muse2/muse/widgets/visibletracks.cpp b/muse2/muse/widgets/visibletracks.cpp index 1b549975..7e56bb36 100644 --- a/muse2/muse/widgets/visibletracks.cpp +++ b/muse2/muse/widgets/visibletracks.cpp @@ -139,7 +139,7 @@ void VisibleTracks::visibilityChanged(QAction* action) VisibleTracks::~VisibleTracks() { - delete actions; + delete [] actions; } } // namespace MusEWidget diff --git a/muse2/synti/fluidsynth/fluidsynti.cpp b/muse2/synti/fluidsynth/fluidsynti.cpp index a03c5da8..cc5c496a 100644 --- a/muse2/synti/fluidsynth/fluidsynti.cpp +++ b/muse2/synti/fluidsynth/fluidsynti.cpp @@ -115,6 +115,17 @@ FluidSynth::FluidSynth(int sr, pthread_mutex_t *_Globalsfloader_mutex) : Mess(2) FluidSynth::~FluidSynth() { + + for (std::list::iterator it =stack.begin(); it !=stack.end(); it++) + { + if(it->intid == FS_UNSPECIFIED_FONT || it->intid == FS_UNSPECIFIED_ID) + continue; + //Try to unload soundfont + int err = fluid_synth_sfunload(fluidsynth, it->intid, 0); + if(err == -1) + std::cerr << DEBUG_ARGS << "Error unloading soundfont!" << fluid_synth_error(fluidsynth) << std::endl; + } + int err = delete_fluid_synth (fluidsynth); if(gui) delete gui; -- cgit v1.2.3