diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
new file mode 100644
index 0000000..5c70232
--- /dev/null
+++ b/.idea/dataSources.xml
@@ -0,0 +1,23 @@
+
+
+
+
+ sqlite.xerial
+ true
+ org.sqlite.JDBC
+ jdbc:sqlite:$PROJECT_DIR$/music_database
+
+
+
+ $ProjectFileDir$
+
+
+ file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/xerial/sqlite-jdbc/3.45.1.0/sqlite-jdbc-3.45.1.0.jar
+
+
+ file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml
new file mode 100644
index 0000000..818c0d7
--- /dev/null
+++ b/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 1d038f9..7c2d85a 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,3 @@
-
diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java
index be474fc..2bb30d0 100644
--- a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java
+++ b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java
@@ -38,4 +38,8 @@ public interface SongSyncAPI {
@GET("/sync/songs/get/notesheet/")
Call downloadNotesheet(@Query("server_filename") String server_filename);
+
+ @Multipart
+ @POST("/ai/regognize/title")
+ Call recognizeTitle(@Part MultipartBody.Part image);
}
diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java
index e1cf87a..60ea902 100644
--- a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java
+++ b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java
@@ -215,6 +215,22 @@ public class SongSyncService {
});
}
+ public void recognizeTitle(String firstNoteSheet, RecognizedSongCallback callback) {
+ RequestBody requestFile = RequestBody.create(MediaType.parse("image/jpeg"), new File(firstNoteSheet));
+ MultipartBody.Part image = MultipartBody.Part.createFormData("image", firstNoteSheet, requestFile);
+ songSyncAPI.recognizeTitle(image).enqueue(new Callback() {
+ @Override
+ public void onResponse(Call call, Response response) {
+ callback.onRecognizedSong(response.body());
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable throwable) {
+ Log.d("SongSyncService", "Recognition failed: " + throwable.getMessage(), throwable);
+ }
+ });
+ }
+
public interface SyncDeletedSongsCallback {
void finishSongSyncing(List remoteDeletedSongs, List localDeletedSongs);
@@ -223,4 +239,8 @@ public class SongSyncService {
public interface UploadNoteSheetCallback {
void finishUploadNoteSheets(List uploadResponses);
}
+
+ public interface RecognizedSongCallback {
+ void onRecognizedSong(AIRecognizedSong aiRecognizedSong);
+ }
}
diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/models/AIRecognizedSong.java b/app/src/main/java/com/stormtales/notevault/network/sync/models/AIRecognizedSong.java
new file mode 100644
index 0000000..fc42783
--- /dev/null
+++ b/app/src/main/java/com/stormtales/notevault/network/sync/models/AIRecognizedSong.java
@@ -0,0 +1,40 @@
+package com.stormtales.notevault.network.sync.models;
+
+public class AIRecognizedSong {
+ private String title;
+ private int year;
+ private String composer;
+ private String description;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public int getYear() {
+ return year;
+ }
+
+ public void setYear(int year) {
+ this.year = year;
+ }
+
+ public String getComposer() {
+ return composer;
+ }
+
+ public void setComposer(String composer) {
+ this.composer = composer;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+}
diff --git a/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java b/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java
index b8af916..ade8b40 100644
--- a/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java
+++ b/app/src/main/java/com/stormtales/notevault/ui/songeditor/SongEditorDialog.java
@@ -6,6 +6,7 @@ import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.text.Layout;
+import android.util.Log;
import android.widget.Button;
import android.widget.EditText;
import androidx.annotation.NonNull;
@@ -20,11 +21,17 @@ import com.stormtales.notevault.R;
import com.stormtales.notevault.data.entities.NoteSheet;
import com.stormtales.notevault.data.entities.Song;
import com.stormtales.notevault.data.sync.SyncStatus;
+import com.stormtales.notevault.network.sync.SongSyncService;
+import com.stormtales.notevault.network.sync.models.AIRecognizedSong;
import com.stormtales.notevault.ui.home.HomeViewModel;
import com.stormtales.notevault.utils.NoteSheetsUtil;
import com.stormtales.notevault.utils.Tupel;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -36,9 +43,12 @@ public class SongEditorDialog extends DialogFragment {
private HomeViewModel homeViewModel;
private Song editedSong;
+ private SongSyncService songSyncService;
+ private View progressbar;
public SongEditorDialog() {
// Required empty public constructor
+ this.songSyncService = new SongSyncService(this.getContext());
}
@@ -49,21 +59,79 @@ public class SongEditorDialog extends DialogFragment {
View dialogView = inflater.inflate(R.layout.fragment_song_editor_dialog, null);
-
dialogView.findViewById(R.id.btnCancel).setOnClickListener(v-> onCancel());
dialogView.findViewById(R.id.btnSave).setOnClickListener(v -> onSave());
+ if(this.noteSheetFiles == null || noteSheetFiles.length == 0) {
+ dialogView.findViewById(R.id.btnAutoDetect).setEnabled(false);
+ } else {
+ progressbar = dialogView.findViewById(R.id.spinnerAutoDetect);
+
+ }
+
+ dialogView.findViewById(R.id.btnAutoDetect).setOnClickListener(v -> {
+ progressbar.setVisibility(ViewGroup.VISIBLE);
+ extractTitleFromFirstPage();
+ });
+
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setCancelable(false);
builder.setView(dialogView);
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
-
-
return dialog;
}
+ private File createTemporaryFileForRecognition(Uri noteSheetUri) {
+ try {
+ // Hole den InputStream des Bildes
+ InputStream inputStream = getContext().getContentResolver().openInputStream(noteSheetUri);
+ if (inputStream != null) {
+ // Erstelle eine temporäre Datei
+ File tempFile = File.createTempFile("temp_note_sheet", ".jpg", getContext().getCacheDir());
+
+ // Inhalt des InputStreams in die temporäre Datei schreiben
+ try (OutputStream outputStream = new FileOutputStream(tempFile)) {
+ byte[] buffer = new byte[8192];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ }
+
+ // Schließe den InputStream
+ inputStream.close();
+
+ return tempFile;
+ }
+ } catch (Exception e) {
+ Log.e("SongEditorDialog", "Fehler beim Erstellen der temporären Datei: " + e.getMessage());
+ }
+
+ return null;
+ }
+ private void extractTitleFromFirstPage() {
+ if(noteSheetFiles != null && noteSheetFiles.length > 0) {
+ Uri firstPageUri = noteSheetFiles[0];
+
+ // Temporäre Datei erstellen
+ File tempFile = createTemporaryFileForRecognition(firstPageUri);
+ if(tempFile != null) {
+ songSyncService.recognizeTitle(tempFile.getAbsolutePath(), new SongSyncService.RecognizedSongCallback() {
+ @Override
+ public void onRecognizedSong(AIRecognizedSong aiRecognizedSong) {
+ progressbar.setVisibility(ViewGroup.GONE);
+ ((EditText) dialog.findViewById(R.id.etTitle)).setText(aiRecognizedSong.getTitle());
+ ((EditText) dialog.findViewById(R.id.etComposer)).setText(aiRecognizedSong.getComposer());
+ ((EditText) dialog.findViewById(R.id.etYear)).setText(String.valueOf(aiRecognizedSong.getYear()));
+ ((EditText) dialog.findViewById(R.id.etGenre)).setText(aiRecognizedSong.getDescription());
+ }
+ });
+ }
+ }
+ }
+
@Override
public void onStart() {
super.onStart();
@@ -97,13 +165,12 @@ public class SongEditorDialog extends DialogFragment {
} else {
Song song = new Song(title, composer, genre, releaseYear);
- List noteSheetList = new ArrayList<>();
Context context = this.getContext();
+ List noteSheetList = new ArrayList<>();
for(Uri uri : noteSheetFiles) {
Tupel result = NoteSheetsUtil.saveImageInternally(context.getContentResolver(), uri, context.getFilesDir());
noteSheetList.add(new NoteSheet(result.getValue00(), result.getValue01()));
}
-
homeViewModel.addSong(song, noteSheetList);
}
diff --git a/app/src/main/res/layout/fragment_song_editor_dialog.xml b/app/src/main/res/layout/fragment_song_editor_dialog.xml
index eefee44..306a975 100644
--- a/app/src/main/res/layout/fragment_song_editor_dialog.xml
+++ b/app/src/main/res/layout/fragment_song_editor_dialog.xml
@@ -96,6 +96,30 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end">
+
+
+
+
+