1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Rosegarden 5 A sequencer and musical notation editor. 6 Copyright 2000-2021 the Rosegarden development team. 7 See the AUTHORS file for more details. 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. See the file 13 COPYING included with this distribution for more information. 14 */ 15 16 #define RG_MODULE_STRING "[LSCPPatchExtractor]" 17 18 #include "LSCPPatchExtractor.h" 19 20 #include <QFile> 21 #include <QTextStream> 22 #include <QStringList> 23 #include "misc/Debug.h" 24 25 class QFile; 26 class QTextStream; 27 class QString; 28 29 namespace Rosegarden 30 { 31 32 bool 33 LSCPPatchExtractor::isLSCPFile(const QString& fileName) 34 { 35 QFile file(fileName); 36 if (!file.open(QFile::ReadOnly)) { 37 return false; 38 } else { 39 QTextStream check(&file); 40 while (!check.atEnd()) { 41 QString currentLine = check.readLine(); 42 if (currentLine.contains("sfArk")) { 43 44 // Crappy, but I have no better ideas. We know for a FACT if 45 // you try to import programs from a .sfArk file, Rosegarden 46 // will end up running isLSCPFile() on it, and it will otherwise 47 // test true, and result in a crash. I could set up some 48 // QProcess thing with a call to file and grep or whatever, but 49 // I'm just going to hard code this function to reject sfArk 50 // files. Be my guest to engineer a much more elegant solution, 51 // because one is certainly possible! 52 RG_WARNING << "Some doofus tried to import a .sfArk file. I'm aborting so we avoid crashing later."; 53 return false; 54 55 56 } else if (currentLine.contains("map", Qt::CaseInsensitive)) { //CaseInsensitive - you could never be sure 57 58 // This attempt to determine a valid file apparently returns 59 // true with completely invalid binary files, but not knowing 60 // anything about the LSCP format, I have no better ideas. This 61 // thing must have come in as a patch I committed on someone's 62 // behalf, because I certainly didn't write this patch 63 // extractor. 64 RG_DEBUG << "MAP string found!"; 65 return true; 66 } 67 } 68 RG_WARNING << "Has extension, but it will not be useful!"; 69 return false; 70 } 71 } 72 73 LSCPPatchExtractor::Device 74 LSCPPatchExtractor::extractContent(const QString& fileName) 75 { 76 /////// Works for single device midi mappings! 77 78 Device device; 79 80 QFile lscpFile(fileName); 81 QTextStream inStream(&lscpFile); 82 83 QStringList splitLine; 84 85 // unsigned int bank, program; 86 std::string programName; 87 std::string bankName; 88 std::string tempDeviceName, tempBankName; 89 90 if (!lscpFile.open(QFile::ReadOnly)) { 91 return device; 92 } else { 93 while (!inStream.atEnd()) { 94 QString currentLine = inStream.readLine(); 95 currentLine = currentLine.simplified(); 96 97 Bank_Prog currentDevice; 98 99 if (!currentLine.isEmpty() && currentLine.startsWith("add", Qt::CaseInsensitive)) { 100 101 ///// Useless for now. Will be needed if someone dedicates time to implement Device import! 102 // std::cout << "Usao sam u ADD!"; 103 // 104 // splitLine = splitQuotedString(currentLine); 105 // tempDeviceName = splitLine.at(2).latin1(); 106 // //debug 107 // for (int i = 0; i < splitLine.size(); i++) std::cout << splitLine.at(i) << std::endl; 108 // std::cout << " " << tempDeviceName << std::endl; 109 110 } else if (!currentLine.isEmpty() && currentLine.startsWith("map", Qt::CaseInsensitive)) { 111 112 // std::cout << "Usao sam u MAP!"; 113 114 unsigned int positionOfBankElement = 3; //position of element in QStringList if NON_MODAL element is absent 115 unsigned int positionOfProgramElement = 4; //similar to above 116 unsigned int positionOfPatchFileName = 6; //we extract bank name from filesystem's file name. 117 118 splitLine = splitQuotedString(currentLine); 119 120 if (splitLine.at(2) == "NON_MODAL") { 121 // Shifting position of elements if optional element (NON MODAL) is present 122 positionOfBankElement = 4; 123 positionOfProgramElement = 5; 124 positionOfPatchFileName = 7; 125 } 126 127 //Getting bank name HACK!!! Not in specification, so we use filename! 128 QString patchFileName = splitLine.at(positionOfPatchFileName); 129 QStringList splitPatchFileName = patchFileName.split("/"); 130 QString temp = splitPatchFileName.at(splitPatchFileName.size()-1); 131 temp = temp.replace("x20"," "); 132 temp = temp.remove(".gig"); 133 134 currentDevice.bankName = temp.toStdString(); 135 currentDevice.bankNumber = splitLine.at(positionOfBankElement).toInt(); 136 currentDevice.programNumber = splitLine.at(positionOfProgramElement).toInt(); 137 138 QString quotedName = splitLine.at(splitLine.size() - 1); 139 // Chacking for another optional element. This one is even more strange - program name may be absent as well! 140 if (quotedName.isEmpty() || 141 quotedName.contains("ON_DEMAND") || 142 quotedName.contains("ON_DEMAND_HOLD") || 143 quotedName.contains("PERSISTENT")) { 144 currentDevice.programName = "Unnamed instrument"; 145 } else { 146 currentDevice.programName = quotedName.toStdString(); 147 } 148 149 device.push_back(currentDevice); 150 } 151 152 } 153 return device; 154 } 155 } 156 157 } 158