rokkonet

PC・Androidソフトウェア・アプリの開発・使い方に関するメモ

SMBサーバーからランダムに1つの音声ファイルを取得するkotlinコード

2022 Feb. 13
2021 Sep. 18.
2021 Sep. 12.

SMBサーバーへの接続にjcifs-ngを利用する。

data class AudioFileProperty(val smbPath: String, val fileSize: Long)
val audioExtension: String = "\\.mp3|\\.wav|\\.aac|\\.au|\\.gsm|\\.m4a|\\.ogg|\\.flac"


    /*
     * ランダムにSMBサーバーの音楽ファイルを1つ選び、そのパスとファイルサイズをAudioFilePropertyデータクラスで返す
     *  data class AudioFileProperty(val smbPath: String, val fileSize: Long)
     * 失敗した時は AudioFileProperty("",0L) を返す。
     * 変数smbは、jcifs-ngによって取得したSmbFileインスタンス
     * audioExtensionは、音声ファイル拡張子集合の文字列
     *  val audioExtension: String = "\\.mp3|\\.wav|\\.aac|\\.au|\\.gsm|\\.m4a|\\.ogg|\\.flac"
     */
    fun selectAudioSmbFile(smb: SmbFile, audioExtension: String ): AudioFileProperty {
        try {
            if (smb.isDirectory) {
                // get all files in dir
                var smbNormalFiles: MutableList<SmbFile>
                var tmpSmbNormalFiles: MutableList<SmbFile> = mutableListOf()
                smbNormalFiles = getNormalSmbFiles(smb, tmpSmbNormalFiles)
                if (1 > smbNormalFiles.size) {
                    // No file in the directory
                    return AudioFileProperty("",0L)
                } else if (1 == smbNormalFiles.size) {
                    // only one file in the directory
                    if (!isMatchTail(smbNormalFiles[0].name, audioExtension)) {
                        // No audio file
                        return AudioFileProperty("",0L)
                    } else {
                        // Got one sound file
                        return AudioFileProperty(smbNormalFiles[0].path, smbNormalFiles[0].length())
                    }
                } else { // smbNormalFiles.size > 1
                    // in case of plural files.
                    // collect audio files to audioSmbFiles
                    var audioSmbFiles: MutableList<SmbFile> = mutableListOf()
                    for (eachSmbNormalFile in smbNormalFiles) {
                        if (isMatchTail(eachSmbNormalFile.name, audioExtension)) {
                            audioSmbFiles.add(eachSmbNormalFile)
                        }
                    }

                    if (1 > audioSmbFiles.size) {
                        // No audio file
                        return AudioFileProperty("",0L)
                    } else if (1 == audioSmbFiles.size) {
                        // Got one sound file
                        return AudioFileProperty(audioSmbFiles[0].path, audioSmbFiles[0].length())
                    } else { // audioSmbFiles.size > 1
                        // select one audio file randomly
                        val countFiles: Int = audioSmbFiles.size
                        val random = Random()
                        val randomNum = random.nextInt(countFiles)
                        // Got one sound file
                        return AudioFileProperty(audioSmbFiles[randomNum].path, audioSmbFiles[randomNum].length())
                    }
                }
            } else if (smb.isFile) {
                if (!isMatchTail(smb.name, audioExtension)) {
                    // No audio file
                    return AudioFileProperty("",0L)
                } else { // a normal file
                    // Got one sound file
                    return AudioFileProperty(smb.path, smb.length())
                }
            } else { // in case of smb is abnormal
                return AudioFileProperty("",0L)
            }
        } catch (e: Exception) {
            return AudioFileProperty("",0L)
        }
    }
/*
    * SMBサーバーのすべてのノーマルファイルを取得する再帰関数
    * パラメータ
    *   givenDir  取得対象のSMBディレクトリパス。
    *   tmpSmbNormalFiles  空のMutableList<SmbFile>型変数。
    *       1つ前の再帰関数実行結果を次の再帰関数に渡すための変数。
    *       ユーザーは最初にこの関数を起動するので、空のMutableListを与える。
    */
    private fun getNormalSmbFiles(givenDir: SmbFile, tmpSmbNormalFiles: MutableList<SmbFile>): MutableList<SmbFile> {
        val childSmbs = givenDir.listFiles()
        if (childSmbs.size > 0) {
            for (eachChild in childSmbs) {
                if (eachChild.isDirectory) {
                    getNormalSmbFiles(eachChild, tmpSmbNormalFiles)
                } else if (eachChild.isFile) {
                    tmpSmbNormalFiles.add(eachChild)
                } else {
                    continue
                }
            }
        }
        return tmpSmbNormalFiles
    }


    /*
     * target文字列の一番後ろのピリオド以降にconditionStr正規表現文字列が含まれていればtrueを返す
     */
    private fun isMatchTail(target: String, conditionStr: String): Boolean {
        // target中の一番後ろのピリオド(ファイル拡張子の区切り)の場所を検出する
        val idxStr = target.lastIndexOf(".")
        if (idxStr < 0) {
            return false
        }
        // targetから、ピリオドから末尾までの文字列を切り出す
        val extenStr = target.substring(idxStr)
        // 切り出した文字列がconditionStrに一致するか調べる
        val regex = (conditionStr+"$").toRegex(RegexOption.IGNORE_CASE)
        return regex.containsMatchIn(extenStr)
    }