|
@@ -5,8 +5,10 @@ import android.arch.lifecycle.ViewModel
|
|
|
import android.content.ContentResolver
|
|
|
import android.content.Context
|
|
|
import android.media.MediaMetadataRetriever
|
|
|
+import com.bomostory.sceneeditmodule.Config
|
|
|
import com.bomostory.sceneeditmodule.basicdata.*
|
|
|
import com.bomostory.sceneeditmodule.utils.FileUtils
|
|
|
+import com.bomostory.sceneeditmodule.utils.MusicPlayerV2
|
|
|
import com.bomostory.sceneeditmodule.utils.TimeUtils
|
|
|
import com.example.bomocloud.BoMoCloud
|
|
|
import com.example.bomocloud.video.UploadVideoData
|
|
@@ -37,6 +39,10 @@ class MovieEditViewModel : ViewModel() {
|
|
|
|
|
|
val musicLiveData = MutableLiveData<Music>()
|
|
|
|
|
|
+ val musicPlayPosition = MutableLiveData<Int>()
|
|
|
+
|
|
|
+ val showProgressingLiveData = MutableLiveData<Boolean>()
|
|
|
+
|
|
|
val musicListLiveData = MutableLiveData<List<Music>>().apply {
|
|
|
value = ArrayList()
|
|
|
}
|
|
@@ -59,6 +65,8 @@ class MovieEditViewModel : ViewModel() {
|
|
|
|
|
|
var musicSource = MusicSource()
|
|
|
|
|
|
+ private val musicPlayer = MusicPlayerV2()
|
|
|
+
|
|
|
|
|
|
fun parseDeviceMusic(contentResolver: ContentResolver) {
|
|
|
val libMusicPaths = ArrayList<String?>()
|
|
@@ -69,19 +77,134 @@ class MovieEditViewModel : ViewModel() {
|
|
|
musicSource.device = DataParser.parseMusic(contentResolver, libMusicPaths)
|
|
|
}
|
|
|
|
|
|
- fun exportEditAudio(music: Music, outputFile: File): Observable<String> {
|
|
|
- if (music.endTime - music.startTime > storyPeriodLiveData.value ?: 0) {
|
|
|
- music.endTime = music.startTime + (storyPeriodLiveData.value ?: 0)
|
|
|
+ fun importMusic(music: Music) {
|
|
|
+ val musics: ArrayList<Music> = musicListLiveData.value as ArrayList<Music>
|
|
|
+ project?.let {
|
|
|
+ val musicFile = File(music.path)
|
|
|
+ val outputFile = createMusicFile()
|
|
|
+
|
|
|
+ outputFile?.let {
|
|
|
+ musicFile.copyTo(it)
|
|
|
+ music.path = it.path
|
|
|
+ }
|
|
|
+ }
|
|
|
+ musics.add(music)
|
|
|
+ musicListLiveData.value = musics
|
|
|
+ musicLiveData.value = music
|
|
|
+ }
|
|
|
+
|
|
|
+ fun importEditMusic(music: Music) {
|
|
|
+ val musics: ArrayList<Music> = musicListLiveData.value as ArrayList<Music>
|
|
|
+ val outputFile = createMusicFile()
|
|
|
+ outputFile?.let {
|
|
|
+ if (music.endTime - music.startTime > storyPeriodLiveData.value ?: 0) {
|
|
|
+ music.endTime = music.startTime + (storyPeriodLiveData.value ?: 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ val audioEditorBuilder = AudioEditor.Builder(mediaHelper)
|
|
|
+ audioEditorBuilder.editAudioFile = File(music.path)
|
|
|
+ audioEditorBuilder.startTime = TimeUtils.getEncodeTimeFormt(music.startTime)
|
|
|
+ audioEditorBuilder.endTime = TimeUtils.getEncodeTimeFormt(music.endTime)
|
|
|
+ audioEditorBuilder.volume = music.volume
|
|
|
+
|
|
|
+ val audioEditor = audioEditorBuilder.build()
|
|
|
+ audioEditor.output(it)
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .doOnSubscribe {
|
|
|
+ showProgressingLiveData.value = true
|
|
|
+ }
|
|
|
+ .doFinally {
|
|
|
+ showProgressingLiveData.value = false
|
|
|
+ }.subscribe({
|
|
|
+ music.path = outputFile.path
|
|
|
+ musics[musics.indexOf(musicLiveData.value)] = music
|
|
|
+ musicListLiveData.value = musics
|
|
|
+ musicLiveData.value = music
|
|
|
+ }, {
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun setMusicLoopEnable(enable: Boolean) {
|
|
|
+ val musics: ArrayList<Music> = musicListLiveData.value as ArrayList<Music>
|
|
|
+ musicLiveData.value?.let {
|
|
|
+ it.isLoop = enable
|
|
|
+ musics[musics.indexOf(it)] = it
|
|
|
+ }
|
|
|
+ musicListLiveData.value = musics
|
|
|
+ }
|
|
|
+
|
|
|
+ fun deleteMusic() {
|
|
|
+ val musics: ArrayList<Music> = musicListLiveData.value as ArrayList<Music>
|
|
|
+ musics.remove(musicLiveData.value)
|
|
|
+ musicListLiveData.value = musics
|
|
|
+ if (musics.size > 0) {
|
|
|
+ musicLiveData.value = musics[0]
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fun precastMusic(music: Music) {
|
|
|
+ musicPlayer.apply {
|
|
|
+ this.music = music
|
|
|
+ stop()
|
|
|
+ init()
|
|
|
+ start()
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ fun playMusic(music: Music, startPosition: Int) {
|
|
|
+ musicPlayer.apply {
|
|
|
+ this.music = music
|
|
|
+ playChangedListener = object : MusicPlayerV2.OnPlayChangedListener {
|
|
|
+ override fun onPlayChanged(position: Int) {
|
|
|
+ musicPlayPosition.postValue(position)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ init()
|
|
|
+ seekTo(startPosition)
|
|
|
+ start()
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- val audioEditorBuilder = AudioEditor.Builder(mediaHelper)
|
|
|
- audioEditorBuilder.editAudioFile = File(music.path)
|
|
|
- audioEditorBuilder.startTime = TimeUtils.getEncodeTimeFormt(music.startTime)
|
|
|
- audioEditorBuilder.endTime = TimeUtils.getEncodeTimeFormt(music.endTime)
|
|
|
- audioEditorBuilder.volume = music.volume
|
|
|
+ fun pauseMusic(){
|
|
|
+ musicPlayer.pause()
|
|
|
+ }
|
|
|
+
|
|
|
+ fun stopMusic(){
|
|
|
+ musicPlayer.stop()
|
|
|
+ }
|
|
|
+
|
|
|
+ fun setMusicVolume(volume: Float) {
|
|
|
+ musicPlayer.setVolume(volume)
|
|
|
+ }
|
|
|
+
|
|
|
+ fun uploadVideo(context: Context, file: File, project: Project): Observable<UploadVideoData> {
|
|
|
+ val id = context.getString(R.string.bomo_cloud_client_id)
|
|
|
+ val secret = context.getString(R.string.bomo_cloud_client_secret)
|
|
|
+ val author = project.author ?: ""
|
|
|
+ val name = project.name ?: ""
|
|
|
+ val category = project.category.id
|
|
|
+ val filePart = MultipartBody.Part.createFormData("file", file.name, RequestBody.create(MediaType.parse("video/*"), file))
|
|
|
+ return BoMoCloud(id, secret).videoService
|
|
|
+ .uploadVideo(author, name, category, filePart)
|
|
|
+ }
|
|
|
|
|
|
- val audioEditor = audioEditorBuilder.build()
|
|
|
- return audioEditor.output(outputFile)
|
|
|
+ fun saveProject(context: Context, project: Project, oldName: String): Completable {
|
|
|
+ var newProject = project
|
|
|
+ project.name?.let { projectName ->
|
|
|
+ if (projectName != oldName) {
|
|
|
+ newProject = com.bomostory.sceneeditmodule.utils.FileUtils.changeProjectName(oldName, projectName)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return FileUtils.saveProject(context, newProject, 1920, 1080)
|
|
|
+ .andThen {
|
|
|
+ onProjectSavedListeners.forEach { it.run() }
|
|
|
+ it.onComplete()
|
|
|
+ }
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
}
|
|
|
|
|
|
private fun parseThemeMusic(project: Project): ArrayList<Music> {
|
|
@@ -114,31 +237,34 @@ class MovieEditViewModel : ViewModel() {
|
|
|
return totalPeriod
|
|
|
}
|
|
|
|
|
|
- fun uploadVideo(context: Context, file: File, project: Project): Observable<UploadVideoData> {
|
|
|
- val id = context.getString(R.string.bomo_cloud_client_id)
|
|
|
- val secret = context.getString(R.string.bomo_cloud_client_secret)
|
|
|
- val author = project.author ?: ""
|
|
|
- val name = project.name ?: ""
|
|
|
- val category = project.category.id
|
|
|
- val filePart = MultipartBody.Part.createFormData("file", file.name, RequestBody.create(MediaType.parse("video/*"), file))
|
|
|
- return BoMoCloud(id, secret).videoService
|
|
|
- .uploadVideo(author, name, category, filePart)
|
|
|
- }
|
|
|
+ private fun createMusicFile(): File? {
|
|
|
+ project?.let {
|
|
|
+ val musicPath = "${FileUtils.getProjectPath(it)}/${Config.MUSIC_FOLDER_NAME}"
|
|
|
+ val fileName = "${System.currentTimeMillis()}.mp3"
|
|
|
+ val outputFile = File(musicPath, fileName)
|
|
|
|
|
|
- fun saveProject(context: Context, project: Project, oldName: String): Completable {
|
|
|
- var newProject = project
|
|
|
- project.name?.let { projectName ->
|
|
|
- if (projectName != oldName) {
|
|
|
- newProject = com.bomostory.sceneeditmodule.utils.FileUtils.changeProjectName(oldName, projectName)
|
|
|
+ val parentFile = outputFile.parentFile
|
|
|
+ if (!parentFile.exists() || !parentFile.isDirectory) {
|
|
|
+ parentFile.mkdirs()
|
|
|
}
|
|
|
+
|
|
|
+ return outputFile
|
|
|
}
|
|
|
- return FileUtils.saveProject(context, newProject, 1920, 1080)
|
|
|
- .andThen {
|
|
|
- onProjectSavedListeners.forEach { it.run() }
|
|
|
- it.onComplete()
|
|
|
+ return null
|
|
|
+ }
|
|
|
+
|
|
|
+ fun onDestroy() {
|
|
|
+ musicPlayer.release()
|
|
|
+
|
|
|
+ project?.let {
|
|
|
+ val musicPath = "${FileUtils.getProjectPath(it)}/${Config.MUSIC_FOLDER_NAME}"
|
|
|
+ val musicFolder = File(musicPath)
|
|
|
+ if (musicFolder.exists()) {
|
|
|
+ for (file in musicFolder.listFiles()) {
|
|
|
+ file.delete()
|
|
|
}
|
|
|
- .subscribeOn(Schedulers.io())
|
|
|
- .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|