Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#2: Voice notes #42

Merged
merged 46 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b800474
SVG commands
shubertm Oct 1, 2023
c4624e9
SVG creating + parsing
shubertm Oct 5, 2023
39febc4
Merge remote-tracking branch 'origin/main' into graphic-notes
shubertm Oct 25, 2023
07c404e
Fix svg read/write + some refactors
shubertm Oct 26, 2023
a783848
Refactor repos and notes models
shubertm Oct 30, 2023
1b7bf94
Merge branch 'main' into graphic-notes
shubertm Oct 30, 2023
4679884
Improving graphic notes
shubertm Nov 8, 2023
6be6aea
Fix gradle build
shubertm Nov 8, 2023
8ae4e43
Merge main
shubertm Nov 9, 2023
39018e6
Fix build errors + deprecated API
shubertm Nov 16, 2023
211a347
Minor fixes + refactor
shubertm Nov 21, 2023
bd1dce5
Fix svg parsing
shubertm Nov 23, 2023
2feb09a
Merge branch 'main' into graphic-notes
shubertm Nov 23, 2023
9ab8c0d
Fix SVG to use proper data structure for commands
shubertm Nov 24, 2023
b1e0ff0
Refactor SVG command
shubertm Nov 25, 2023
9a038ac
Minor refactoring
kirillt Nov 27, 2023
9d08558
Update app/src/main/res/values/strings.xml
shubertm Nov 28, 2023
51edfda
Refactor SVG viewbox
shubertm Nov 29, 2023
964df38
Replace Stack with ArrayDeque
shubertm Nov 29, 2023
b32f933
Add type annotations to public SVG functions
shubertm Nov 29, 2023
77c66a8
Refactor SVG commands
shubertm Nov 29, 2023
4eac79d
Move local texts to string resource file
shubertm Nov 29, 2023
3858f14
Remove non-null assertions in NotesListAdapter
shubertm Nov 29, 2023
56e0e5f
Remove non-null assertions in MemoPreferencesImpl
shubertm Nov 29, 2023
a3bb1a5
Minor refactor
shubertm Nov 30, 2023
80fd06d
Check svg paths size
shubertm Dec 1, 2023
50a7117
Generalize file listing function
shubertm Dec 3, 2023
b433636
Refactor repos
shubertm Dec 3, 2023
a709241
Minor refactors
shubertm Dec 4, 2023
2de93c3
Fix extra line feed in text content
shubertm Dec 4, 2023
17d5097
Minor refactor
shubertm Dec 5, 2023
e41726d
Add extended fab
shubertm Dec 6, 2023
f6139b7
Minor refacotrs
shubertm Dec 6, 2023
e77fb6a
Voice notes impl
shubertm Dec 18, 2023
c0994a9
SVG creating + parsing
shubertm Oct 5, 2023
21b5490
Refactor repos and notes models
shubertm Oct 30, 2023
39168a1
Improving graphic notes
shubertm Nov 8, 2023
e393e8f
Fix build errors + deprecated API
shubertm Nov 16, 2023
505fc6e
Fix svg parsing
shubertm Nov 23, 2023
0643661
Fix SVG to use proper data structure for commands
shubertm Nov 24, 2023
04fdcd5
Voice notes impl
shubertm Dec 18, 2023
f727ddd
Some fixes
shubertm Dec 21, 2023
2986176
Some fixes
shubertm Dec 21, 2023
4486fb7
Merge remote-tracking branch 'origin/feature/voice-notes' into featur…
shubertm Dec 21, 2023
0b8c4a2
Improvements
shubertm Dec 23, 2023
8c2b75e
Merge main
shubertm Jan 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,6 @@ dependencies {

implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.9'

implementation 'com.google.code.gson:gson:2.10.1'

testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
Expand Down
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>

<application
android:name=".App"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package dev.arkbuilders.arkmemo.contracts

import android.Manifest
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.RequiresApi
import com.simplemobiletools.commons.helpers.PERMISSION_RECORD_AUDIO

class PermissionContract: ActivityResultContract<String, Boolean>() {

Expand All @@ -19,4 +22,4 @@ class PermissionContract: ActivityResultContract<String, Boolean>() {
override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
return Environment.isExternalStorageManager()
}
}
}
21 changes: 21 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/di/MediaModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dev.arkbuilders.arkmemo.di

import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import dev.arkbuilders.arkmemo.media.ArkMediaPlayer
import dev.arkbuilders.arkmemo.media.ArkMediaPlayerImpl
import dev.arkbuilders.arkmemo.media.ArkAudioRecorder
import dev.arkbuilders.arkmemo.media.ArkAudioRecorderImpl

@Module
@InstallIn(SingletonComponent::class)
abstract class MediaModule {

@Binds
abstract fun bindArkAudioRecorder(impl: ArkAudioRecorderImpl): ArkAudioRecorder

@Binds
abstract fun bindArkMediaPlayer(impl: ArkMediaPlayerImpl): ArkMediaPlayer
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import dev.arkbuilders.arkmemo.repo.NotesRepo
import dev.arkbuilders.arkmemo.repo.text.TextNotesRepo
import dev.arkbuilders.arkmemo.models.GraphicNote
import dev.arkbuilders.arkmemo.models.TextNote
import dev.arkbuilders.arkmemo.models.VoiceNote
import dev.arkbuilders.arkmemo.preferences.MemoPreferences
import dev.arkbuilders.arkmemo.repo.NotesRepoHelper
import dev.arkbuilders.arkmemo.repo.voices.VoiceNotesRepo


@InstallIn(SingletonComponent::class)
Expand All @@ -24,6 +26,9 @@ abstract class RepositoryModule {
@Binds
abstract fun bindGraphicNotesRepo(impl: GraphicNotesRepo): NotesRepo<GraphicNote>

@Binds
abstract fun bindVoiceNotesRepo(impl: VoiceNotesRepo): NotesRepo<VoiceNote>

companion object {
@Provides
fun provideNotesRepoHelper(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.arkbuilders.arkmemo.media

import java.nio.file.Path

interface ArkAudioRecorder {

fun init()

fun start()

fun pause()

fun stop()

fun resume()

fun reset()

fun maxAmplitude(): Int

fun getRecording(): Path
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package dev.arkbuilders.arkmemo.media

import android.content.Context
import android.media.MediaRecorder
import android.os.Build
import dagger.hilt.android.qualifiers.ApplicationContext
import java.nio.file.Path
import javax.inject.Inject
import kotlin.io.path.createTempFile

class ArkAudioRecorderImpl @Inject constructor(
@ApplicationContext private val context: Context
): ArkAudioRecorder {

private var recorder: MediaRecorder? = null

private val tempFile = createTempFile().toFile()

override fun init() {
recorder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
MediaRecorder(context)
else MediaRecorder()
recorder?.apply {
setAudioSource(MediaRecorder.AudioSource.VOICE_RECOGNITION)
setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP)
setOutputFile(tempFile)
setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
prepare()
}
}

override fun start() {
recorder?.start()
}

override fun pause() {
recorder?.pause()
}

override fun resume() {
recorder?.resume()
}

override fun reset() {
recorder?.reset()
}

override fun stop() {
recorder?.let {
it.stop()
it.release()
}
recorder = null
}

override fun maxAmplitude(): Int = recorder?.maxAmplitude!!

override fun getRecording(): Path = tempFile.toPath()
}
25 changes: 25 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/media/ArkMediaPlayer.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package dev.arkbuilders.arkmemo.media

import android.media.MediaPlayer

interface ArkMediaPlayer:
MediaPlayer.OnCompletionListener,
MediaPlayer.OnPreparedListener,
MediaPlayer.OnSeekCompleteListener {

fun init(path: String, onCompletion: () -> Unit, onPrepared: () -> Unit)

fun play()

fun stop()

fun pause()

fun seekTo(position: Int)

fun duration(): Int

fun currentPosition(): Int

fun isPlaying(): Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package dev.arkbuilders.arkmemo.media

import android.media.AudioAttributes
import android.media.MediaPlayer
import javax.inject.Inject

class ArkMediaPlayerImpl @Inject constructor(): ArkMediaPlayer {

private var player: MediaPlayer? = null

private var onCompletionHandler: () -> Unit = {}
private var onPreparedHandler: () -> Unit = {}

override fun init(path: String, onCompletion: () -> Unit, onPrepared: () -> Unit) {
onCompletionHandler = onCompletion
onPreparedHandler = onPrepared
player = MediaPlayer().apply {
setOnCompletionListener(this@ArkMediaPlayerImpl)
setOnPreparedListener(this@ArkMediaPlayerImpl)
setAudioAttributes(
AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
.setUsage(AudioAttributes.USAGE_MEDIA)
.build()
)
setDataSource(path)
prepare()
}
}

override fun play() {
player?.start()
}

override fun stop() {
player?.let {
it.stop()
it.release()
}
player = null
}

override fun pause() {
player?.pause()
}

override fun seekTo(position: Int) {
player?.seekTo(position)
}

override fun duration(): Int = player?.duration!!

override fun currentPosition(): Int = player?.currentPosition!!

override fun isPlaying(): Boolean = player?.isPlaying!!

override fun onCompletion(player: MediaPlayer?) {
onCompletionHandler()
}

override fun onPrepared(player: MediaPlayer?) {
onPreparedHandler()
}

override fun onSeekComplete(player: MediaPlayer?) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class GraphicNote(
override val title: String = "",
val description: String = "",
override val description: String = "",
@IgnoredOnParcel
val svg: SVG? = null,
@IgnoredOnParcel
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/dev/arkbuilders/arkmemo/models/Note.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ import dev.arkbuilders.arklib.data.index.Resource

interface Note {
val title: String
val description: String
var resource: Resource?
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import kotlinx.parcelize.Parcelize
@Parcelize
data class TextNote (
override val title: String = "",
val description: String = "",
override val description: String = "",
val text: String = "",
@IgnoredOnParcel
override var resource: Resource? = null
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/dev/arkbuilders/arkmemo/models/VoiceNote.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.arkbuilders.arkmemo.models

import android.os.Parcelable
import dev.arkbuilders.arklib.data.index.Resource
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import java.nio.file.Path
import kotlin.io.path.createTempFile

@Parcelize
class VoiceNote(
override val title: String = "",
override val description: String = "",
val duration: String = "",
@IgnoredOnParcel
var path: Path = createTempFile(),
@IgnoredOnParcel
override var resource: Resource? = null
): Note, Parcelable
Loading
Loading