How to fix midi inputfilestream error in JUCE? - readfile

I am trying to read the midi file into a sequence in JUCE, but when I run it, there is an error showed up saying there is something wrong with my inputfilestream.
I started from the audio-application template and write the midi read-in code in getNextBlock() function.
File midiPath("/Desktop/input.midi");
FileInputStream myStream(midiPath);
MidiFile midifile;
midifile.readFrom(myStream);
int NumofTrack = midifile.getNumTracks();
std::cout<<"The track number:"<<NumofTrack<<std::end;
I just wanna test the readin function in the JUCE, and it doesn't work. The error showed as "juce_FileInputStream.cpp":
int64 FileInputStream::getTotalLength()
{
// You should always check that a stream opened successfully before using it!
jassert (openedOk()); <-- errror here
...

Try:
File midiPath = File::getSpecialLocation(File::SpecialLocationType::userDesktopDirectory).getChildFile("input.midi");
FileInputStream myStream(midiPath);
MidiFile midifile;
midifile.readFrom(myStream);
int NumofTrack = midifile.getNumTracks();
std::cout<<"The track number:"<<NumofTrack<<std::end;

Related

Arduino IDE ESP32 device using SPIFFS to save

I writing ESP32 program and using SPIFFS to save some data because I do not want to loose it after I power down the device.
I have 2 functions:
char* readFile(fs::FS &fs, const char *path)
{
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file || file.isDirectory())
{
Serial.println("Failed to open file for reading");
return "FAIL";
}
Serial.print("Read from file: ");
while (file.available())
{
Serial.write(file.read());
delayMicroseconds(100);
//TODO
//append all characters and return it as a list of char arrays at the end of reading
}
file.close();
}
void writeFile(fs::FS &fs, const char *path, const char *message)
{
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file)
{
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message))
{
Serial.println("File written");
}
else
{
Serial.println("Write failed");
}
file.close();
}
First of all, I run my program and call writeFile() and then followed by readFile():
int n = 0;
Wifi_setup();
Spiffs_setup();
n = scan_wifi_networks();
Serial.print("list_strings outside scan function = ");
for (int i = 0 ; i<=n ; i++){
Serial.println(found_networks[i]);
}
//compare list_strings with preset wifi networks. If match, everything is fine, if not, problem!
writeFile(SPIFFS, "/wifi.txt", "Telia-33F8A3-Greitas");
char* known_networks = readFile(SPIFFS, "/wifi.txt");
//send USD to the server, go back to sleep
//initialize_deep_sleep();
}
And that part works fine. From the serial monitor, I can see that it have sucesfully written my text to wifi.txt.
After I run write/read functions
Next, I comment out write function and only leave read function.I run the code again and it is not able to read back my text:
Only readFile
Can someone help me understand why is that happening? I thought that if I write to spiffs once, I will be able to access it afterwards but that is not the case. I have previously used EEPROM and that seemed to work. I can write to EEPROM address and simply access the same address later and the value will still be there after the power off. Any help is appreciated. Thanks in advance.
UPDATE1
I have managed to read back data from my SPIFFS after I wrote to it. I had missed one crucial step:
https://randomnerdtutorials.com/install-esp32-filesystem-uploader-arduino-ide/
However, now, I am encountering another issue:
In my project folder, I have created a folder "data" which is supposed to be accessed by SPIFFS. In there, I create 2 files :
wifi.txt
update.bin
update.bin for now is not relevant. Lets talk about wifi.txt
After I have written to Spiffs, I now comment out the writeFile function and only leave out readFile. The result from my serial monitor:
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4
Listing directory: /
FILE: /update.bin SIZE: 0
FILE: /wifi.txt SIZE: 20
Reading file: /wifi.txt
Read from file: Telia-33F8A3-Greitas
As you can see from the serial monitor above, my program recognises the text that I have written to my spifs /wifi.txt file. Howeverm when I go to my actual project directory and open data/wifi.txt it is emtpy:
How can this happen? My program recongises that theres data inside but it wont show up in the file.
UPDATE2
I have done some further testing of SPIFFS.
In my data folder, I have created another txt file test.txt. In there, I have manually put some text "this is text message".
In my program, I have called function:
char* returned_data = readFile(SPIFFS, "/test.txt");
And the serial monitor sucesfully printed the message that I have put. So that proves that the SPIFFS is able to read back from the files without any issues.
Then, I have modified my program:
writeFile(SPIFFS, "/test.txt", "hello123");
char* returned_data = readFile(SPIFFS, "/test.txt");
The code above should overwrite whatever I have written to my txt file with "hello123" and then my program should read the "hello123" back from Spiffs. The serial monitor response:
Listing directory: /
FILE: /update.bin SIZE: 0
FILE: /wifi.txt SIZE: 2
FILE: /test.txt SIZE: 8
Writing file: /test.txt
File written
Reading file: /wifi.txt
Read from file:
Reading file: /test.txt
Read from file: hello123
As you can see, it is able to sucesfully read back "hello123".
HOWEVER, when I go to my project folder, open the data/test.txt, I can still see my initial text not replaced with "hello123".
I do not understand how is this happening..

Problem with esp8266 sending large JSON Document via MQTT

I developed a little application that read data from a sensor, store them in SPIFFS memory of my wemos D1 mini (esp8266) and then create a JSON Document and send it via MQTT to my topic. The problem is that as long as I send a JSON Doc with 10 object everything works great, but when I increase the size of the doc over 10 object nothing works. Eventually I need to send a JSON doc with 100 object inside.
What have I already done?
I'm using PubSubClient and I already set the MAX_PACKET_SIZE to the correct value
Using arduinojson assistant I found out the size of my JSON Document (8192 bytes)
I tried to use mqtt.fx to test if the problem was the esp8266 or the mqtt broker. Using mqtt.fx I'm able to send a JSON doc with 100 objects
As soon as I increase the size of the JSON doc I get a wdt error from the serial monitor of my arduino IDE.
I search the internet for wdt error but I don't get what they are and how to solve my problem
Last things I already tried to show on the serial monitor the file.txt in the SPIFFS where I store the data and I can store and then read the 100 object
So in the end I think it's an esp8266 problem and not PubSubClient or MQTT. Am I right?
Does anyone of you here ever encountered this problem before or have some other test I can run?
I search the internet for wdt error but I don't get what they are and how to solve my problem
WDT stands for a Watch Dog Timer. https://os.mbed.com/cookbook/WatchDog-Timer#:~:text=A%20watchdog%20timer%20(WDT)%20is,a%20software%20or%20hardware%20fault.
A watchdog timer (WDT) is a hardware timer that automatically generates a system reset if the main program neglects to periodically service it. It is often used to automatically reset an embedded device that hangs because of a software or hardware fault. Some systems may also refer to it as a computer operating properly (COP) timer. Many microcontrollers including the mbed processor have watchdog timer hardware.
Let's paint a better picture with an example. Let's say that you setup a WDT with a time of 10 seconds. Then the WDT starts counting down from 10 seconds. If it reaches 0 the processor will reset. "Feeding" the WDT will reset the countdown to the original value in this case 10 seconds. So if the WDT has counted down to 4 seconds remaining and you feed it, it resets the countdown back to 10 and starts counting down again.
Does anyone of you here ever encountered this problem before or have some other test I can run?
It looks to me like sending a larger JSON object takes a longer period of time than what the WDT is set for. One possibility would be to break up the JSON object into multiple pieces and send it in smaller chunks instead of one large one. This way the time between WDT "feedings" is reduced. I have no idea if this would be possible for you to change. But this should at least give you a better idea of what's happening.
OK in the end the problem was that sending a large JsonDocument triggered the WDT and the only way I found to overcome this problem was, as suggested by adamvz, to create a main file with all the 100 object, then call a function to split that file in 10 smaller one and send each of them over the internet through an HTTP request or Mosquitto.
Supposing you already created the main file in the spiffs memory, then:
This to split the main file:
void WritePacks() {
sourceFile = LittleFS.open("/file.txt", "r");
if (!sourceFile) {
Serial.println(F("Error: file.txt open failed"));
} else {
Serial.println("File open w/ success");
for (byte idx = 0; idx < outputCount; idx++) {
String aLine;
aLine.reserve(capacity);
if (sourceFile.available() == 0) break;
destinationFile = LittleFS.open(outputFileNames[idx], "w");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
int lineCount = 0;
while (sourceFile.available() && (lineCount <= 10)) {
aLine = sourceFile.readStringUntil('\n');
destinationFile.println(aLine); // double check if the '\n' is in the String or not (--> print or println accordingly)
lineCount++;
}
outputIndex = idx;
Serial.println(outputIndex);
destinationFile.close();
}
} // end for
sourceFile.close();
}
}//end WritePacks
This to publish:
//------ HTTP Publish ------
void httpPublish(){
const char * outputFileNames[] = {"/out1.txt", "/out2.txt", "/out3.txt", "/out4.txt", "/out5.txt", "/out6.txt", "/out7.txt", "/out8.txt", "/out9.txt", "/out10.txt"};
const byte outputCount = sizeof outputFileNames / sizeof outputFileNames[0];
byte outputIndex = 0;
File sourceFile;
File destinationFile;
//Serial.println(capacity);
for (byte idx = 0; idx < outputCount; idx++) {
DynamicJsonDocument doc(capacity);
DynamicJsonDocument globalDoc(capacity);
StaticJsonDocument <1024> localDoc;
String aLine;
aLine.reserve(capacity);
destinationFile = LittleFS.open(outputFileNames[idx], "r");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
Serial.print("Reading: ");
Serial.println(outputFileNames[idx]);
//int lineCount = 0;
while (destinationFile.available()) {
aLine = destinationFile.readStringUntil('\n');
DeserializationError error = deserializeJson(localDoc, aLine);
if (!error) globalDoc.add(localDoc);
else{ Serial.println("Error Writing All files");}
}//while
JsonObject Info = doc.createNestedObject("Info");
Info["Battery"] = battery;
Info["ID"] = id;
Info["Latitudine"] = latitudine;
Info["Longitudine"] = longitudine;
JsonArray Data = doc.createNestedArray("Data");
Data.add(globalDoc);
HTTPClient http;
//Send request
http.begin("yourURL");
char buffer[capacity];
size_t n = serializeJson(doc, buffer);
http.POST(buffer);
Serial.println(buffer);
http.end();
destinationFile.close();
}
}// end for
}//end httpPublish

fopen / ofstream::open fail when creating a BMP file

Years ago I created a C++ function using FILE to create bitmap files. Recently (not sure when or why) this code is now failing when opening the file. The problem is with the open call ...
file_ptr = fopen("ScreenShots/Screenshot1.bmp", "wb");
Currently this results in an error 13, permission denied error. Change the filename extension to something else and the fopen works fine. For example,
file_ptr = fopen("ScreenShots/Screenshot1.bm2", "wb");
The file saves correctly and when changing the extension back to BMP I can display the file correctly in Paintshop.
Did a quick check using ofstream and same problem.
Any ideas why I get a permission denied error when trying to open BMP files to write data? For information I am using Visual Studio Community 2017 on Windows 10.
To give the complete section of code ...
BITMAPFILEHEADER bitmap_header;
BITMAPINFOHEADER bitmap_info;
FILE *file_ptr;
unsigned int count;
unsigned char tempRGB;
char filename[256];
bool finished;
// CREATE A UNIQUE FILENAME
count = 1;
finished = false;
do
{
// CREATE NAME
sprintf(filename, "ScreenShots/Screenshot%d.bmp", count);
// CHECK IF FILE EXISTS
errno = 0;
file_ptr = fopen(filename, "rb");
if (file_ptr)
{
// FILE EXISTS
fclose(file_ptr);
count = count + 1;
}
else
{
// UNIQUE FILENAME
file_ptr = fopen(filename, "wb");
if (file_ptr == NULL)
{
// UNABLE TO OPEN FOR WRITING - GIVE UP
// (USING OWN LOGGING CLASS)
jalog.log("\nERROR on Screenshot >");
jalog.log(filename);
jalog.log("< >");
jalog.log((short)errno);
return;
}
finished = true;
}
}
while (finished == false);
I've managed to find the issue ... Avast antivirus. I noticed that trying to do an open action for a BMP file took a few seconds while opening any other file type (successfully or unsuccessfully) was instantaneous. As something similar happens when running new programs I tried disabling all the Avast shields and I could successfully create a BMP file using the existing code.
For my own personal use I can whitelist my own programs, but annoying if I get to distributing the program to other people.
Thanks for the help ... and sorry for raising a C++ issue that in the end had nothing to do with C++!

How do I properly close my BinaryReader class so I can open the same file again?

Using VC++ 2010, .NET 3.5
My app is crashing on the 2nd iteration of this do..while loop on this line
System::IO::BinaryReader^ binReader = ...
.
System::String^ fileName = GetFileName();
bool continue = true;
do {
System::IO::BinaryReader^ binReader = gcnew System::IO::BinaryReader(System::IO::File::Open(fileName, System::IO::FileMode::Open));
//
// read file,
// do things,
//
binReader.close();
delete binReader;
} while (continue);
It compiles fine, but when run, I get the "..stopped working" dialog (on the 2nd iteration, I checked by putting a ::MessageBox() at the beginning of the loop)
How do I properly close my BinaryReader class so I can open the same file again?

Download a single .txt using QFtp

I've got a problem with QFtp. I wanna download a single .txt file with a single line(8 bytes) from my server, so I've written the following code, but it doesn't work.
The file "actions.txt" were created in the folder1 directory. I can see the size of it pretty well in the client-side. But the file is not being written. I'm getting an empty file.
QFile* actionFile = new QFile("action.txt");
QFtp *ftp = new QFtp(parent);
void Dialog::getActionFile()
{
actionFile->open(QIODevice::WriteOnly);
ftp->connectToHost("mydomain.de");
ftp->login("user", "pw");
ftp->cd("folder1");
ftp->get("action.txt",actionFile);
ftp->close();
actionFile->close();
}
Thanks in advance.
The documentation of several methods of QFtp says:
The function does not block and returns immediately. The command is
scheduled, and its execution is performed asynchronously. The function
returns a unique identifier which is passed by commandStarted() and
commandFinished().
So you need to wait for the appropriate signals to be emitted.
Note that you can also use QNetworkRequest to request the whole ftp URL (I think even with username and password inside the URL) to download the file.
I solved my problem.
I treated one step each time the commandFininshed signal was emitted.
like this:
void MainWindow::ftpCommandFinished(int id, bool error)
{
static bool flag = false;
if(ftp->currentCommand() == QFtp::ConnectToHost)
checkUpdate();
if(ftp->currentCommand() == QFtp::Get)
{
file->close();
if(error)
{
QMessageBox::warning(this, "Erro!", ftp->errorString());
deleteLater();
return;
}
if(!flag)
checkVersion();
else{
delete ftp, file;
ftp = 0; file = 0;
}
flag = true;
}
}
the reason of the flag variable is something else that needs further explanations about the program, so i won't go down that road.
Thanks for you help. It somehow helped me a lot.