Automatic Recognize Title
This commit is contained in:
parent
648bd66ba4
commit
6f6f8cf605
23
.idea/dataSources.xml
Normal file
23
.idea/dataSources.xml
Normal file
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="music_database" uuid="eb23f694-6586-450b-8f6f-a75731d36b96">
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/music_database</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
<libraries>
|
||||
<library>
|
||||
<url>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</url>
|
||||
</library>
|
||||
<library>
|
||||
<url>file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.45.1/org/slf4j/slf4j-api/1.7.36/slf4j-api-1.7.36.jar</url>
|
||||
</library>
|
||||
</libraries>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
18
.idea/deploymentTargetSelector.xml
Normal file
18
.idea/deploymentTargetSelector.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2025-04-10T18:07:32.446414465Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=R52N50NLGRT" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
@ -1,4 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
|
@ -38,4 +38,8 @@ public interface SongSyncAPI {
|
||||
|
||||
@GET("/sync/songs/get/notesheet/")
|
||||
Call<ResponseBody> downloadNotesheet(@Query("server_filename") String server_filename);
|
||||
|
||||
@Multipart
|
||||
@POST("/ai/regognize/title")
|
||||
Call<AIRecognizedSong> recognizeTitle(@Part MultipartBody.Part image);
|
||||
}
|
||||
|
@ -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<AIRecognizedSong>() {
|
||||
@Override
|
||||
public void onResponse(Call<AIRecognizedSong> call, Response<AIRecognizedSong> response) {
|
||||
callback.onRecognizedSong(response.body());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<AIRecognizedSong> call, Throwable throwable) {
|
||||
Log.d("SongSyncService", "Recognition failed: " + throwable.getMessage(), throwable);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public interface SyncDeletedSongsCallback {
|
||||
void finishSongSyncing(List<String> remoteDeletedSongs, List<Integer> localDeletedSongs);
|
||||
@ -223,4 +239,8 @@ public class SongSyncService {
|
||||
public interface UploadNoteSheetCallback {
|
||||
void finishUploadNoteSheets(List<UploadResponse> uploadResponses);
|
||||
}
|
||||
|
||||
public interface RecognizedSongCallback {
|
||||
void onRecognizedSong(AIRecognizedSong aiRecognizedSong);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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<NoteSheet> noteSheetList = new ArrayList<>();
|
||||
Context context = this.getContext();
|
||||
List<NoteSheet> noteSheetList = new ArrayList<>();
|
||||
for(Uri uri : noteSheetFiles) {
|
||||
Tupel<String, String> result = NoteSheetsUtil.saveImageInternally(context.getContentResolver(), uri, context.getFilesDir());
|
||||
noteSheetList.add(new NoteSheet(result.getValue00(), result.getValue01()));
|
||||
}
|
||||
|
||||
homeViewModel.addSong(song, noteSheetList);
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,30 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
<!-- ProgressBar als Spinner -->
|
||||
<ProgressBar
|
||||
android:id="@+id/spinnerAutoDetect"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:baselineAligned="false"
|
||||
|
||||
android:visibility="gone"
|
||||
android:indeterminate="true" />
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnAutoDetect"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Automatische Erkennung"
|
||||
android:textColor="@color/light_blue_600"
|
||||
android:paddingEnd="16dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:textSize="16sp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:fontFamily="sans-serif-medium" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnCancel"
|
||||
|
Loading…
Reference in New Issue
Block a user