modulemanager.cpp 8.83 KB
Newer Older
Leander Schulten's avatar
Leander Schulten committed
1
2
3
#include "modulemanager.h"
#include <QLibrary>
#include "module.h"
Leander Schulten's avatar
Leander Schulten committed
4
#include <QDebug>
5
#include "settings.h"
Leander Schulten's avatar
Leander Schulten committed
6
7
#include <QJsonObject>
#include <QJsonArray>
8
#include "audio/audiocapturemanager.h"
Leander Schulten's avatar
Leander Schulten committed
9
10
11

namespace Modules {

Leander Schulten's avatar
Leander Schulten committed
12
13
14
namespace detail {

    PropertyInformation::PropertyInformation(const QJsonObject &o):name(o["name"].toString("no name")),
15
16
        description(o["description"].toString()),type(static_cast<Type>(o["type"].toInt())),max(o["maxValue"].toInt()),
        min(o["minValue"].toInt()),defaultValue(o["defaultValue"].toInt()){
Leander Schulten's avatar
Leander Schulten committed
17
18
19
20
21
22
23

    }

    void PropertyInformation::writeJsonObject(QJsonObject &o)const{
            o["type"] = type;
            o["name"] = name;
            o["description"] = description;
24
25
26
            o["minValue"] = min;
            o["maxValue"] = max;
            o["defaultValue"] = defaultValue;
Leander Schulten's avatar
Leander Schulten committed
27
28
29
30
31
32
    }

}

Module::Module(const QJsonObject &o):name(o["name"].toString("no name")),
    description(o["description"].toString()),code(o["code"].toString()),
33
34
    inputType(static_cast<ValueType>(o["inputType"].toInt())),
    outputType(static_cast<ValueType>(o["outputType"].toInt())),
Leander Schulten's avatar
Leander Schulten committed
35
36
37
38
39
40
41
42
43
44
45
46
    type(static_cast<Type>(o["type"].toInt())){
    QJsonArray a = o["properties"].toArray();
    for(const auto i : a){
        QJsonObject ob = i.toObject();
        properties.push_back(new detail::PropertyInformation(ob));
    }
}

void Module::writeJsonObject(QJsonObject &o)const{
    o["name"] = name;
    o["description"] = description;
    o["code"] = code;
47
48
    o["inputType"] = inputType;
    o["outputType"] = outputType;
Leander Schulten's avatar
Leander Schulten committed
49
50
51
52
53
54
55
56
57
58
    o["type"] = type;
    QJsonArray a;
    for(const auto & p : properties){
        QJsonObject prop;
        p->writeJsonObject(prop);
        a.append(prop);
    }
    o["properties"] = a;
}

Leander Schulten's avatar
Leander Schulten committed
59
60
61
62
63
64
typedef  bool (*Have_Func)(MODUL_TYPE t);


typedef unsigned int (*GetNumberOfProgramms)();
typedef std::string (*GetNameOfProgramm)(unsigned int index);
typedef std::string (*GetDescriptionOfProgramm)(unsigned int index);
Leander Schulten's avatar
Leander Schulten committed
65
typedef Modules::Program* (*CreateProgramm)(unsigned int index);
Leander Schulten's avatar
Leander Schulten committed
66
67
68

    ModuleManager::ModuleManager()
    {
69
70
71
72
73
74
75
76
        fftOutputView = Audio::AudioCaptureManager::get().getFFTOutput();
        QObject::connect(&Audio::AudioCaptureManager::get(),&Audio::AudioCaptureManager::capturingStatusChanged,[this](){
            for(const auto & info : loadedLibraryMap){
                if(info.second.supportAudioFunc){
                    info.second.supportAudioFunc(Audio::AudioCaptureManager::get().isCapturing());
                }
            }
        });
Leander Schulten's avatar
Leander Schulten committed
77
78
    }

Leander Schulten's avatar
Leander Schulten committed
79
80
81
82
83
84
85
86
    void ModuleManager::loadModules(const QJsonObject & o){
        QJsonArray a = o["modules"].toArray();
        for(const auto _o : a){
            QJsonObject ob = _o.toObject();
            modules.push_back(new Module(ob));
        }
    }

87
88
89
90
91
    bool ModuleManager::unloadLibrary(QString filePath){
        for(auto e = loadedLibraryMap.begin();e!=loadedLibraryMap.end();++e){
            qDebug()<<e->first;
            if(e->first == filePath){
                filter.erase(std::remove_if(filter.begin(),filter.end(),[&](const auto &f){
92
                    return f.libraryIdentifier == e->second.libraryIdentifier;
93
94
                }),filter.cend());
                programms.erase(std::remove_if(programms.begin(),programms.end(),[&](const auto &f){
95
                    return f.libraryIdentifier == e->second.libraryIdentifier;
96
97
                }),programms.cend());
                consumer.erase(std::remove_if(consumer.begin(),consumer.end(),[&](const auto &f){
98
                    return f.libraryIdentifier == e->second.libraryIdentifier;
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
                }),consumer.cend());
                QLibrary lib(filePath);
                bool suc = lib.unload();
                if(suc){
                   loadedLibraryMap.erase(e);
                   QFile f(filePath);
                   if(!f.remove()){
                       return f.rename(f.fileName()+".old");
                   }
                   return true;
                }
                int counter = 0;
                while (QFile::exists(filePath+ QString::number(counter)+".old")) {
                    ++counter;
                }
                suc = QFile(filePath).rename(filePath+ QString::number(counter)+".old");
                if(suc){
                    loadedLibraryMap.erase(e);
                }
                return suc;
            }
        }
        return true;
    }

Leander Schulten's avatar
Leander Schulten committed
124
125
126
127
128
129
130
131
132
133
    void ModuleManager::writeJsonObject(QJsonObject &o){
        QJsonArray a ;
        for(const auto &m : modules){
            QJsonObject ob;
            m->writeJsonObject(ob);
            a.append(ob);
        }
        o["modules"] = a;
    }

134
    void ModuleManager::loadModule(QString name, bool replaceNewInPBs){
Leander Schulten's avatar
Leander Schulten committed
135
        qDebug()<<"load lib  : " << name;
Leander Schulten's avatar
Leander Schulten committed
136
137
138
        QLibrary lib(name);
        if(lib.load()){
            Have_Func f = reinterpret_cast<Have_Func>(lib.resolve("have"));
Leander Schulten's avatar
Leander Schulten committed
139
140
            if(!f){
                qDebug()<<"have funktion is missing";
Leander Schulten's avatar
Leander Schulten committed
141
                return;
Leander Schulten's avatar
Leander Schulten committed
142
            }
143
144
145
            auto lastProgram  = programms.size();
            auto lastFilter   = filter   .size();
            auto lastConsumer = consumer .size();
Leander Schulten's avatar
Leander Schulten committed
146
            if(f(MODUL_TYPE::Program)){
Leander Schulten's avatar
Leander Schulten committed
147
                loadType(lib,programms,"Program",lastLibraryIdentifier);
Leander Schulten's avatar
Leander Schulten committed
148
            }if(f(MODUL_TYPE::LoopProgram)){
149
                //loadType(lib,programms,"LoopProgramm",lastLibraryIdentifier);
Leander Schulten's avatar
Leander Schulten committed
150
            }if(f(MODUL_TYPE::Filter)){
151
                loadType(lib,filter,"Filter",lastLibraryIdentifier);
Leander Schulten's avatar
Leander Schulten committed
152
            }if(f(MODUL_TYPE::Consumer)){
Leander Schulten's avatar
Leander Schulten committed
153
                qDebug()<< "Loading Consumer";
154
                loadType(lib,consumer,"Consumer",lastLibraryIdentifier);
Leander Schulten's avatar
Leander Schulten committed
155
            }
156
157
158
159
160
161
162
            SupportAudioFunc supportAudioFunc = nullptr;
            if(f(MODUL_TYPE::Audio)){
                //qDebug()<< "Loading Audio";
                supportAudioFunc = loadAudio(lib,&fftOutputView);
            }
            lastLibraryIdentifier++;
            loadedLibraryMap.emplace_back(lib.fileName(),LibInfo{lastLibraryIdentifier,supportAudioFunc});
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
            if(replaceNewInPBs){
                for(const auto & pb : ProgramBlockManager::model){
                    for(;lastProgram<programms.size();lastProgram++){
                        for(const auto & v : pb->getUsedProgramsByName(programms[lastProgram].name())){
                            pb->replaceProgram(v,std::shared_ptr<Program>(programms[lastProgram].create()));
                        }
                    }
                    for(;lastFilter<filter.size();lastFilter++){
                        for(const auto & v : pb->getUsedFiltersByName(filter[lastFilter].name())){
                            pb->replaceFilter(v,std::shared_ptr<Filter>(filter[lastFilter].create()));
                        }
                    }
                    for(;lastConsumer<consumer.size();lastConsumer++){
                        for(const auto & v : pb->getUsedConsumersByName(consumer[lastConsumer].name())){
                            pb->replaceConsumer(v,std::shared_ptr<Consumer>(consumer[lastConsumer].create()));
                        }
                    }
                }
            }
Leander Schulten's avatar
Leander Schulten committed
182
        }else{
183
            qDebug()<<"Cant load lib :" << name<< " because : " << lib.errorString() ;
Leander Schulten's avatar
Leander Schulten committed
184
185
186
187
        }
    }

    void ModuleManager::loadAllModulesInDir(QDir dir){
Leander Schulten's avatar
Leander Schulten committed
188
189
         qDebug() << dir;
        for(auto s : dir.entryInfoList(QDir::Files)){
190
191
192
            if(s.suffix() == "old"){
                QFile::remove(s.filePath());
            }
193
194
195
            if(QLibrary::isLibrary(s.fileName())){
                loadModule(s.absoluteFilePath());
            }
196
            //qDebug()<<"found : " << s;
Leander Schulten's avatar
Leander Schulten committed
197
        }
198
        for(auto s : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)){
199
200
            loadAllModulesInDir(s);
        }
Leander Schulten's avatar
Leander Schulten committed
201
        for(const auto & m : getProgrammModules())
202
            qDebug() << m.name().c_str();
Leander Schulten's avatar
Leander Schulten committed
203
        for(const auto & m : getFilterModules())
204
            qDebug() << m.name().c_str();
Leander Schulten's avatar
Leander Schulten committed
205
        for(const auto & m : getConsumerModules())
206
207
            qDebug() << m.name().c_str();

Leander Schulten's avatar
Leander Schulten committed
208
209
    }

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227


    ModuleManager::SupportAudioFunc ModuleManager::loadAudio(QLibrary & lib, Modules::FFTOutputView<float> * fftOutputView){
        //typedef void (*SupportAudioFunc )(bool);
        typedef void (*SetFFTOutputViewFunc )(Modules::FFTOutputView<float>*);
        //using SupportAudioFunc = unsigned int (bool);
        //using SetFFTOutputViewFunc = char const * (Modules::FFTOutputView<float>*);
        auto supportAudioFunc = reinterpret_cast<SupportAudioFunc>(lib.resolve("_supportAudio"));
        auto setFFTOutputViewFunc = reinterpret_cast<SetFFTOutputViewFunc>(lib.resolve("_setFFTOutputView"));
        if (!supportAudioFunc || !setFFTOutputViewFunc) {
            qDebug() << "Error loading audio functions : "<< supportAudioFunc << setFFTOutputViewFunc;
            return nullptr;
        }
        setFFTOutputViewFunc(fftOutputView);
        supportAudioFunc(Audio::AudioCaptureManager::get().isCapturing());
        return  supportAudioFunc;
    }

Leander Schulten's avatar
Leander Schulten committed
228
}
229