Kartenloser Modus?

Es wäre super, wenn der Tonuino eine Möglichkeit hätte, auch ohne Karte einen Ordner zu wählen.
Das Thema wurde im Forum schon mal aufgeworfen, dann aber anscheinend nicht weiter verfolgt.
Gefunden habe ich jedenfalls nichts.

Ich hätte das gerne aus zwei Gründen:
-Mein Sohnemann ist echt gut darin, die Karten verschwinden zu lassen.
-Auf unseren Tonuinos gibt es auch Ordner mit „Elternmusik“, für die ich ungern Karten anlege.

Die Bedienung stelle ich mir so vor:
Vor- und Zurück Tasten gleichzeitig lange drücken.
Dann sollte ein voice-Menü wie beim Anlernen von Karten starten: „Wähle den Ordner aus, den du abspielen möchtest und bestätige mit der Pausetaste“
Auswahl des Ordners wie beim Anlernen von Karten mit kurzem/langem Tastendruck, Ansage Ordnernummer und Anspielen des ersten Stücks im Ordner.
Nach Auswahl des Ordners mit der Pausetaste bestätigen.
Jetzt sollte die Wiedergabe im Albummodus starten. Also mit den Tasten stoppen, starten und zum nächsten / vorigen Titel springen.

Meine Programmierkenntnisse sind -höflich ausgedrückt- etwas rudimentär.
Ich fange trotzdem mal an, zu basten.
Vielleicht klappt es ja doch :thinking:

Falls einer unserer Softwarespezialisten Zeit und Lust hat, würde ich mich sehr über Unterstützung freuen.

Sowas in der Art steht noch auf meiner ToDo Liste für meinen nächsten Tonuino (da mobil, sollte er zur Not auch mal ohne Karte gestartet werden können). Aber ich kann noch nicht sagen, wann ich dazu komme, das zu programmieren, da erstmal die Hardware stehen muss und die Software an die HW angepasst werden muss… Auch ein paar andere SW Änderungen müssen davor rein… kann also noch nichts versprechen…

Bin auch kein Programmierkünstler :wink:, arbeite mich auch gerade in den Code ein.

Ach ja, evtl. hilft dir das auch etwas weiter

Als Tipp kann ich dir geben:
Schau dir die Methoden „playFolder()“, sowie " voiceMenue()" genauer an.
damit solltest du schnell ans Ziel kommen.
Die Meisten komplexeren Funktionen sind schon in Methoden verfasst.

1 „Gefällt mir“

Hallo, danke für Eure Antworten.
Hatte gehofft, dass jemand die Funktion schon so ähnlich realisiert hat und ich sie nur im Forum nicht finde.
Ich baue auf der 2.1 von Thorsten auf.
Bis jetzt hab ich den dreitasten-Shortcut vom Adminmenü kopiert und auf die 2 Tasten umgebaut.
Die zwei von Marco genannten Funktionen hatte ich schon gefunden. Der erste Versuch damit war nix. Muss mich noch besser reinfuchsen, was da alles beim Funktionsaufruf übergeben werden muss.
Die Unterlagen von AZ habe ich mir runtergeladen.
Mal schauen :crossed_fingers:

Eventuell bekommt man es über einen Modifier hin. Sprich du legst eine spezielle Karte auf und hättest dann eine Art Dateimanager (über 3/5 Buttons und Sprache - komfortabel wird es nicht).

1 „Gefällt mir“

Ich habe inzwischen mal angefangen und alles Mögliche zusammengeklaut.
Der Aufruf über die Tastenkombination funktioniert.
Das Voice Menü kommt auch wie gewünscht und ich kann den Ordner auswählen.
Irgendwas ist aber noch faul.
Gestern hat er nach Bestätigung mit der Pausetaste tatsächlich den gewählten Ordner abgespielt, aber dann nicht immer auf die next/previous Track Befehle reagiert.
Momentan funktioniert es nicht mehr (man sollte vielleicht ab und zu einen funktionierenden Zwischenstand sichern, bevor man ohne viel Ahnung weiter rumbastelt :crazy_face:).
Ich muss noch besser verstehen, was da zwischen den Funktionen alles übergeben wird und wie man nach Auswahl des neuen Ordners wieder in den gleichen Zustand kommt, wie er nach Auswahl über Karte oder Shortcut ist.

Dass es so weit schon funktioniert, ist schon mal ein brauchbarer Zwischenstand.
Mal schauen, was noch geht :smiley:

Tipps und Hilfe sind jederzeit willkommen!

Unten mein aktueller Code, basierend auf der 2.1 Version:

Die Funktion zum Aufruf des Adminmenüs auf zwei Tasten gestutzt, und damit eine eigene Funktion aufgerufen (der Teil ist direkt danach eingefügt):

 //Anfang
if ((upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && upButton.isPressed() && downButton.isPressed()) {
  mp3.pause();
  do {
    readButtons();
  } while (upButton.isPressed() || downButton.isPressed());
  readButtons();
  Serial.println(F("Tastenkombination funktioniert!\n"));
  cardlessPlay();
  break;
}

//Ende

Jetzt die eigentliche Funktion (vor Void Aminmenu eingefügt).

//Anfang: neues Menü cardlessPlay

void cardlessPlay(bool fromCard = false) {
  disablestandbyTimer();
  mp3.pause();
  Serial.println(F("=== cardlessPlay()"));
    
  Serial.print(F(" Aktueller Ordner "));
  Serial.println(myFolder->folder);
  
  Serial.print(F(" Aktueller Modus "));
  Serial.println(myFolder->mode);
  
  //Auf Album Modus schalten
  Serial.println(F("Jetzt umstellen auf Album Modus"));
  myFolder->mode = 2;
  myFolder->folder = 1;
  //Voice Menü: Ordner zum Abspielen wählen und als aktuellen Ordner übernehmen
  
  myFolder->folder = voiceMenu(99, 301, 0, true, 0, 0, true);
  if (myFolder->folder == 0) return false;

  Serial.print(F(" nach Voice Menü "));
  Serial.println(myFolder->folder);

  playFolder();  
  setstandbyTimer();
}

//Ende

Ich würde nur ein mp3.pause verwenden und zwar in deiner cardlessPlay Methode.
Setze ein delay dahinter, der DFPlayer ist Mega zickig. 300-500ms sollten passen.
eventuell kannst du das noch verfeinern, indem du prüfst ob überhaupt was läuft.

if (isPlaying()) {
 mp3.pause();
 delay(500);
}

Dann würde ich mode nicht fest einprogrammieren sondern mit einem Übergabe Parameter einstellen, den kannst du ja optional gestalten, das macht die Methode dynamischer.

folder brauchst du nicht mit 1 überschreiben, du änderst ihn ja eh nochmal mit deinem voiceMenu.

Wie sähe es denn von dir aus? Du scheinst mehr programmieren zu können, das wäre ja eine schnellere und bessere Hilfe, oder? Nur wenn du magst, logisch.

Meine Lösung sähe fast genau so aus, mit den kleinen beschriebenen Änderungen.
Bis auf das Delay, sind die Verbesserungsvorschläge auch nicht funktional, eher strukturell.
Es macht aber auch den größeren Sinn, wenn man sich selbst eine Lösung erarbeitet. Sonst lernt man nichts dazu.

2 „Gefällt mir“

Ich hab das vor ein paar Monaten so bei mir gelöst, dass ich alle Buttons doppelt belegt habe. Per default sind das ja nicht alle. So kann ich nun im laufenden Betrieb, indem ich zum Beispiel Volume+ lange drücke, einen Ordner weiter springen. Track+ lange, sorgt für einen Sprung um 10 Tracks weiter, beide Minus entsprechend äquivalent.
Da bei beiden auch gerne über das Limit der Ordner oder Tracks hinaus gegangen wird, wird das entsprechend abgefangen. Er registriert dabei auch, in welchem Ordner gerade eine Karte ist, bzw, kann ja eh vom zuletzt gespielten Track „resumen“, dank Speicherung im eeprom.

Es gibt auch Boxen, wo ich das via rotary encoder gelöst habe, mal mit integriertem Pushswitch und auch ohne. Experimentierfreudig wie ich bin, habe ich das auch über 0,96" Displays oder ws2812 led als Anzeige, wo man gerade hinnavigiert hat.

In der einfachsten, die als Standard genutzt wird, über Buttons, der Rest dann per define wählbar. War auf jeden Fall schon eine gute Wuselei, die Funktionen auf Module auszulagern.

Ich finde das essentiell, bei solchen Kinder Boxen, erstens, es bleiben Wutanfälle aus, wenn mal die Karten oder Figuren weg sind, aber trotzdem Musik gehört werden möchte (im Urlaub oder bei anderen Kids zu Besuch) und zweitens, wenn man selber mal schnell durch navigieren möchte.

So, jetzt läuft es soweit.

In der zuletzt geposteten Version hat noch die Zeile
„knownCard = false;“ gefehlt; ohne die funktioniert das voiceMenu nicht richtig.

Ich verwende den aktuellen folder als Ausgangswert fürs voiceMenu.
So kann man einfach nur einen Ordner rauf oder runter springen.

Und das Ganze funktioniert nur, wenn bereits ein Titel spielt; ansonsten hängt sich alles auf.

Aktuell habe ich es abgefangen und breche ab, falls gerade nichts spielt.

Kann mir jemand erklären, warum das in diesem Zustand nicht funktioniert, bzw. welche Werte ich setzen müsste um das zu beheben?

Mein Programmierstil fällt wohl eher unter „quick and dirty“, nehmt es mir bitte nicht übel.
Ich poste mein Gebastel trotzdem; vielleicht taugt es ja als Ausgangsbasis für eine eventuelle Übernahme der Funktion in den Standard.
Basis ist die DEV, heruntergeladen am 06.04.2020. Die Zeilenangaben beziehen sich auf die unveränderte DEV Version, also am besten von hinten nach vorne einfügen.

Hier die Änderungen:

Vor „bool knownCard = false;“ (Zeile 81) einzufügen:

//cardlessPlay Beginn
void cardlessPlay(bool fromCard = false);
//cardlessPlay Ende

Vor „if (pauseButton.wasReleased()) {
if (activeModifier != NULL) (…)“
(Zeile 967) einzufügen:

//cardlessPlay Beginn
//Zugang zum VoiceMenü über up&down lang drücken
if ((upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && upButton.isPressed() && downButton.isPressed()) {
  
  //cardlessPlay funktioniert nur, wenn bereits ein Titel läuft. Sonst hängt sich alles auf.
  //Daher abfangen
  if (!isPlaying()) {
    Serial.println(F("Spielt nicht, Abbruch!"));
    break;
  }
  
  mp3.pause();
  do {
    readButtons();
  } while (upButton.isPressed() || downButton.isPressed());
  readButtons();
  Serial.println(F("Ordnerauswahl über Tasten UP/DOWN"));
  delay(500);
      
  cardlessPlay();

  break;
}
//cardlessPlay Ende

Vor "void adminMenu(bool fromCard = false) { " (Zeile1111) einzufügen:

//cardlessPlay Beginn
void cardlessPlay(bool fromCard = false) {
  disablestandbyTimer();
  uint8_t lastFolder;
  mp3.pause();
  Serial.println(F("=== cardlessPlay()"));
  knownCard = false; 

  lastFolder = myFolder->folder;

  //Auf Album Modus schalten
  Serial.println(F("Jetzt umstellen auf Album Modus"));
  myFolder->mode = 2;
 
  //Voice Menü: Ordner zum Abspielen wählen und als aktuellen Ordner übernehmen
  myFolder->folder = voiceMenu(99, 301, 0, true, 0, lastFolder, true);
  if (myFolder->folder == 0) return false;

  Serial.print(F(" nach Voice Menü "));
  Serial.println(myFolder->folder);

  playFolder();
  setstandbyTimer();
}
//cardlessPlay Ende

Moin!

Mir ist der Kartenlose Modus auch nicht aus dem Kopf gegangen und ich möchte Euch meine Herangehensweise präsentieren.
Eigentlich ist ja mit den shortCuts schon eine Möglichkeit gegeben, etwas ohne Karte abzuspielen. Also habe ich die vorhandene Möglichkeit einen shortCut zu konfigurieren einfach um einen shortCut erweitert, der dann nach der Konfiguration sofort startet.
Der Weg über das komplette Adminmenü zum Punkt shortCuts ist zwar nicht wirklich direkt, aber er hat den Vorteil, dass eben alle Ordner und Dateien in allen Modi wie mit den schon programmierten Karten angewählt werden können.
Für eine Notlösung, falls mal eine Karte nicht zur Hand sein sollte, für mich durchaus tragbar.
Hier meine Änderungen zur regulären DEV.

Zeile 62 ersetzen mit:
folderSettings shortCuts[5];

Zeile 1235 ersetzen mit:

uint8_t shortcut = voiceMenu(5, 940, 940);
if (shortcut == 5) {
  setupFolder(&mySettings.shortCuts[4]);
  delay (500);
  playShortCut(4);
  return;
}
else

neue Datei im mp3-Ordner erstellen:
0945_cardlessPlay.mp3 „Wiedergabe ohne Karte konfigurieren und starten.“

Edit2: So, jetzt in etwas hübscher. Man sollte manche Sachen einfach nicht mitten in der Nacht machen :wink:

3 „Gefällt mir“

Nachdem einige Zeit in’s Land gegangen ist, und das Kind doch häufiger als gedacht, die favorisierte Karte verlegt hat, ist mir der Weg über das komplette Adminmenü doch etwas zu umfangreich, so dass ich mir eine direktere Möglichkeit über eine Tastenkombination erarbeitet habe.
Der Grundgedanke, einen shortCut zu benutzen ist geblieben, allerdings rufe ich die Funktion jetzt durch gleichzeitiges langes Drücken des upButtons und des downButtons auf. Es funktioniert nur wenn gerade nicht abgespielt wird.

Meine Änderung der DEV in Zeile 1235 ist also obsolet!

Die Änderung der Zeile 62 bleibt bestehen.

Neu ist eine Änderung der Zeile 972, welche in der original DEV eine Leerzeile sein müsste.

Zeile 972 also ersetzen mit:

if ((upButton.pressedFor(LONG_PRESS) || downButton.pressedFor(LONG_PRESS)) && upButton.isPressed() && downButton.isPressed()) {
  if (!isPlaying()) {
    knownCard = false;
    do {
      readButtons();
    } while (upButton.isPressed() || downButton.isPressed());
    readButtons();
    disablestandbyTimer();
    Serial.println(F("=== ConfigCardlessPlay()"));
    int temp = voiceMenu(2, 945, 933);
    if (temp == 2) {
      setupFolder(&mySettings.shortCuts[4]);
      delay (500);
      playShortCut(4);
      return;
    }
    else {
      Serial.println(F("Abgebrochen!"));
      setstandbyTimer();
      mp3.playMp3FolderTrack(802);
      return;
    }
  }
}