Annotation of nono/host/hostsound.cpp, revision 1.1.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.