Annotation of nono/host/hostsound.cpp, revision 1.1

1.1     ! root        1: //
        !             2: // nono
        !             3: // Copyright (C) 2025 nono project
        !             4: // Licensed under nono-license.txt
        !             5: //
        !             6: 
        !             7: //
        !             8: // サウンドのホストデバイス
        !             9: //
        !            10: 
        !            11: // 再生時のフロー
        !            12: //
        !            13: // Sound Thread             :     Host thread
        !            14: //
        !            15: // HostSoundDevice::Play()  :   HostDevice::ThreadRun
        !            16: //     |
        !            17: //     +-------------->| queue |----+         … 送信キューに追加し
        !            18: //     +-------------->| pipe  |----+         … パイプでホストスレッドに通知
        !            19: //     |                            |
        !            20: //   <-+                    :       v
        !            21: //                                 --- kevent
        !            22: //                          :       |
        !            23: //                              HostSoundDevice::Write()
        !            24: //                          :       |
        !            25: //                              SoundDriver*::Write()
        !            26: //                          :       |
        !            27: //                                  +------> Playback in the real world
        !            28: 
        !            29: #include "hostsound.h"
        !            30: #include "config.h"
        !            31: #include "sound.h"
        !            32: #if defined(HAVE_HOSTSOUND_ALSA)
        !            33: #include "sounddriver_alsa.h"
        !            34: #endif
        !            35: #if defined(HAVE_HOSTSOUND_NETBSD)
        !            36: #include "sounddriver_netbsd.h"
        !            37: #endif
        !            38: #if defined(HAVE_HOSTSOUND_SNDIO)
        !            39: #include "sounddriver_sndio.h"
        !            40: #endif
        !            41: #include "sounddriver_none.h"
        !            42: #include "sounddriver_wav.h"
        !            43: #include "uimessage.h"
        !            44: 
        !            45: // コンストラクタ
        !            46: HostSoundDevice::HostSoundDevice(Device *parent_)
        !            47:        : inherited(parent_, OBJ_HOSTSOUND, ""/*portname*/)
        !            48: {
        !            49:        monitor = gMonitorManager->Regist(ID_MONITOR_HOSTSOUND, this);
        !            50:        monitor->func = ToMonitorCallback(&HostSoundDevice::MonitorUpdate);
        !            51:        monitor->SetSize(48, 6);
        !            52: }
        !            53: 
        !            54: // デストラクタ
        !            55: HostSoundDevice::~HostSoundDevice()
        !            56: {
        !            57: }
        !            58: 
        !            59: // ログレベル設定
        !            60: void
        !            61: HostSoundDevice::SetLogLevel(int loglevel_)
        !            62: {
        !            63:        inherited::SetLogLevel(loglevel_);
        !            64: 
        !            65:        RWLockGuard_Read guard(driverlock);
        !            66:        if ((bool)driver) {
        !            67:                driver->SetLogLevel(loglevel_);
        !            68:        }
        !            69: }
        !            70: 
        !            71: // 動的コンストラクションその2
        !            72: bool
        !            73: HostSoundDevice::Create2()
        !            74: {
        !            75:        if (inherited::Create2() == false) {
        !            76:                return false;
        !            77:        }
        !            78: 
        !            79:        // SelectDriver() は SoundRenderer::Reconfig() から呼ばれるので、
        !            80:        // ここでは不要。
        !            81: 
        !            82:        return true;
        !            83: }
        !            84: 
        !            85: // ドライバ(再)選択。
        !            86: // エラーが起きた場合、
        !            87: // 起動時なら、warn() 等で表示して false を返す(終了する)。
        !            88: // 実行中なら、warn() 等で表示してもいいが、必ず None にフォールバックして
        !            89: // true を返すこと。
        !            90: bool
        !            91: HostSoundDevice::SelectDriver(bool startup)
        !            92: {
        !            93:        auto sound = dynamic_cast<SoundRenderer *>(parent);
        !            94:        freq = sound->GetOutFrequency();
        !            95:        bytes_per_blk = sound->GetOutBytesPerBlk();
        !            96: 
        !            97:        RWLockGuard_Write guard(driverlock);
        !            98: 
        !            99:        driver.reset();
        !           100:        errmsg.clear();
        !           101: 
        !           102:        // ドライバはここで選択。
        !           103:        const ConfigItem& item = gConfig->Find("hostsound-driver");
        !           104:        std::string type = item.AsString();
        !           105: 
        !           106:        // auto は環境による。
        !           107:        if (type == "auto") {
        !           108: #if defined(HAVE_HOSTSOUND_NETBSD)
        !           109:                type = "netbsd";
        !           110: #elif defined(HAVE_HOSTSOUND_SNDIO)
        !           111:                type = "sndio";
        !           112: #elif defined(HAVE_HOSTSOUND_ALSA)
        !           113:                type = "alsa";
        !           114: #else
        !           115:                type = "none";
        !           116: #endif
        !           117:        }
        !           118: 
        !           119:        enum {
        !           120:                ERR_CONFIG,             // 設定でのエラー
        !           121:                ERR_INVALID,    // 知らないドライバ
        !           122:                ERR_NOTSUPP,    // コンパイルされてない
        !           123:        } reason = ERR_CONFIG;
        !           124: 
        !           125:        if (type == "none") {
        !           126:                CreateNone();
        !           127: 
        !           128:        } else if (type == "wav") {
        !           129:                CreateWav();
        !           130: 
        !           131:        } else if (type == "netbsd") {
        !           132: #if defined(HAVE_HOSTSOUND_NETBSD)
        !           133:                CreateNetBSD();
        !           134: #else
        !           135:                reason = ERR_NOTSUPP;
        !           136: #endif
        !           137: 
        !           138:        } else if (type == "sndio") {
        !           139: #if defined(HAVE_HOSTSOUND_SNDIO)
        !           140:                CreateSndIO();
        !           141: #else
        !           142:                reason = ERR_NOTSUPP;
        !           143: #endif
        !           144: 
        !           145:        } else if (type == "alsa") {
        !           146: #if defined(HAVE_HOSTSOUND_ALSA)
        !           147:                CreateALSA();
        !           148: #else
        !           149:                reason = ERR_NOTSUPP;
        !           150: #endif
        !           151: 
        !           152:        } else {
        !           153:                // 知らないドライバ種別
        !           154:                reason = ERR_INVALID;
        !           155:        }
        !           156: 
        !           157:        if ((bool)driver == false) {
        !           158:                // 指定のドライバが使えなかった場合、
        !           159:                // o 起動時ならエラー終了する。
        !           160:                // o 実行中なら none にフォールバックする。
        !           161:                if (startup) {
        !           162:                        switch (reason) {
        !           163:                         case ERR_INVALID:
        !           164:                                item.Err("Invalid driver name");
        !           165:                                break;
        !           166:                         case ERR_CONFIG:
        !           167:                                item.Err("Could not configure the driver");
        !           168:                                warnx("(See details with option -C -Lhostsound=1)");
        !           169:                                break;
        !           170:                         case ERR_NOTSUPP:
        !           171:                                item.Err("HostSound driver %s not compiled", type.c_str());
        !           172:                                break;
        !           173:                         default:
        !           174:                                assert(false);
        !           175:                        }
        !           176:                        return false;
        !           177:                } else {
        !           178:                        gMainApp.GetUIMessage()->Post(UIMessage::HOSTSOUND_FAILED);
        !           179: 
        !           180:                        CreateNone();
        !           181:                }
        !           182:        }
        !           183:        assert((bool)driver);
        !           184: 
        !           185:        // ドライバ名は Capitalize だがログはほぼ小文字なので雰囲気を揃える…
        !           186:        putmsg(1, "selected host driver: %s",
        !           187:                string_tolower(driver->GetDriverName()).c_str());
        !           188: 
        !           189:        return true;
        !           190: }
        !           191: 
        !           192: // None ドライバを生成する。
        !           193: // 戻り値はなく、成否は (bool)driver で判断する。
        !           194: void
        !           195: HostSoundDevice::CreateNone()
        !           196: {
        !           197:        try {
        !           198:                driver.reset(new SoundDriverNone(this));
        !           199:        } catch (...) { }
        !           200:        if ((bool)driver) {
        !           201:                if (driver->InitDriver()) {
        !           202:                        // 成功
        !           203:                        return;
        !           204:                }
        !           205:                errmsg = driver->errmsg;
        !           206:                driver.reset();
        !           207:        }
        !           208: }
        !           209: 
        !           210: // Wav ドライバを生成する。
        !           211: // 戻り値はなく、成否は (bool)driver で判断する。
        !           212: void
        !           213: HostSoundDevice::CreateWav()
        !           214: {
        !           215:        try {
        !           216:                driver.reset(new SoundDriverWav(this));
        !           217:        } catch (...) { }
        !           218:        if ((bool)driver) {
        !           219:                if (driver->InitDriver()) {
        !           220:                        // 成功
        !           221:                        return;
        !           222:                }
        !           223:                errmsg = driver->errmsg;
        !           224:                driver.reset();
        !           225:        }
        !           226: }
        !           227: 
        !           228: #if defined(HAVE_HOSTSOUND_NETBSD)
        !           229: // NetBSD ドライバを生成する。
        !           230: // 戻り値はなく、成否は (bool)driver で判断する。
        !           231: void
        !           232: HostSoundDevice::CreateNetBSD()
        !           233: {
        !           234:        try {
        !           235:                driver.reset(new SoundDriverNetBSD(this));
        !           236:        } catch (...) { }
        !           237:        if ((bool)driver) {
        !           238:                if (driver->InitDriver()) {
        !           239:                        // 成功
        !           240:                        return;
        !           241:                }
        !           242:                errmsg = driver->errmsg;
        !           243:                driver.reset();
        !           244:        }
        !           245: }
        !           246: #endif
        !           247: 
        !           248: #if defined(HAVE_HOSTSOUND_SNDIO)
        !           249: // sndio ドライバを生成する。
        !           250: // 戻り値はなく、成否は (bool)driver で判断する。
        !           251: void
        !           252: HostSoundDevice::CreateSndIO()
        !           253: {
        !           254:        try {
        !           255:                driver.reset(new SoundDriverSndIO(this));
        !           256:        } catch (...) { }
        !           257:        if ((bool)driver) {
        !           258:                if (driver->InitDriver()) {
        !           259:                        // 成功
        !           260:                        return;
        !           261:                }
        !           262:                errmsg = driver->errmsg;
        !           263:                driver.reset();
        !           264:        }
        !           265: }
        !           266: #endif
        !           267: 
        !           268: #if defined(HAVE_HOSTSOUND_ALSA)
        !           269: // ALSA ドライバを生成する。
        !           270: // 戻り値はなく、成否は (bool)driver で判断する。
        !           271: void
        !           272: HostSoundDevice::CreateALSA()
        !           273: {
        !           274:        try {
        !           275:                driver.reset(new SoundDriverALSA(this));
        !           276:        } catch (...) { }
        !           277:        if ((bool)driver) {
        !           278:                if (driver->InitDriver()) {
        !           279:                        // 成功
        !           280:                        return;
        !           281:                }
        !           282:                errmsg = driver->errmsg;
        !           283:                driver.reset();
        !           284:        }
        !           285: }
        !           286: #endif
        !           287: 
        !           288: // サウンドスレッドからの再生(の指示) (サウンドスレッドで呼ばれる)。
        !           289: bool
        !           290: HostSoundDevice::Play(const int16 *blk)
        !           291: {
        !           292:        playq.Enqueue(blk);
        !           293: 
        !           294:        // パイプで通知。
        !           295:        return WritePipe(PIPE_TX);
        !           296: }
        !           297: 
        !           298: // 外部への書き出し (再生)
        !           299: void
        !           300: HostSoundDevice::Write()
        !           301: {
        !           302:        const int16 * const *blkp;
        !           303: 
        !           304:        RWLockGuard_Read guard(driverlock);
        !           305:        assert((bool)driver);
        !           306: 
        !           307:        // 再生リングバッファから1ブロック取り出す。
        !           308:        while ((blkp = playq.BeginRead()) != NULL) {
        !           309:                stat.write_blk++;
        !           310:                driver->Write(*blkp);
        !           311:                playq.EndRead();
        !           312:        }
        !           313: }
        !           314: 
        !           315: // 外部からの読み込み (録音)
        !           316: // 未対応
        !           317: int
        !           318: HostSoundDevice::Read()
        !           319: {
        !           320:        return 0;
        !           321: }
        !           322: 
        !           323: const std::string&
        !           324: HostSoundDevice::GetDriverName()
        !           325: {
        !           326:        RWLockGuard_Read guard(driverlock);
        !           327:        assert((bool)driver);
        !           328:        return driver->GetDriverName();
        !           329: }
        !           330: 
        !           331: // モニタ
        !           332: void
        !           333: HostSoundDevice::MonitorUpdate(Monitor *, TextScreen& screen)
        !           334: {
        !           335:        screen.Clear();
        !           336: 
        !           337:        {
        !           338:                RWLockGuard_Read gurad(driverlock);
        !           339:                screen.Print(0, 0, "HostSound Driver: %s",
        !           340:                        driver->GetDriverName().c_str());
        !           341:                // 次の1行はドライバ依存情報
        !           342:                driver->MonitorUpdateMD(screen, 1);
        !           343:        }
        !           344: 
        !           345:        screen.Print(0, 2, "Output Frequency: %u Hz", freq);
        !           346: 
        !           347:        int y = 4;
        !           348:        screen.Print(0, y++, "%-17s%13s %17s", "<Play>", "Blocks", "Bytes");
        !           349:        screen.Print(0, y++, "%-17s%13s %17s", "Write to host",
        !           350:                format_number(stat.write_blk).c_str(),
        !           351:                format_number(stat.write_blk * bytes_per_blk).c_str());
        !           352: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.