bool AddNew(QWidget *parent, const char *id, const char *name) { obs_source_t source = obs_get_output_source(0); obs_scene_t scene = obs_scene_from_source(source); bool success = false; if (!source) return false; source = obs_get_source_by_name(name); if (source) { QMessageBox::information(parent, QTStr("NameExists.Title"), QTStr("NameExists.Text")); } else { source = obs_source_create(OBS_SOURCE_TYPE_INPUT, id, name, NULL); if (source) { obs_add_source(source); obs_scene_add(scene, source); success = true; } } obs_source_release(source); obs_scene_release(scene); return success; }
static obs_data_t *GenerateSaveData(obs_data_array_t *sceneOrder) { obs_data_t *saveData = obs_data_create(); obs_data_array_t *sourcesArray = obs_save_sources(); obs_source_t *currentScene = obs_get_output_source(0); const char *sceneName = obs_source_get_name(currentScene); const char *sceneCollection = config_get_string(App()->mGetGlobalConfig(), "Basic", "SceneCollection"); SaveAudioDevice(DESKTOP_AUDIO_1, 1, saveData); SaveAudioDevice(DESKTOP_AUDIO_2, 2, saveData); SaveAudioDevice(AUX_AUDIO_1, 3, saveData); SaveAudioDevice(AUX_AUDIO_2, 4, saveData); SaveAudioDevice(AUX_AUDIO_3, 5, saveData); obs_data_set_string(saveData, "current_scene", sceneName); obs_data_set_array(saveData, "scene_order", sceneOrder); obs_data_set_string(saveData, "name", sceneCollection); obs_data_set_array(saveData, "sources", sourcesArray); obs_data_array_release(sourcesArray); obs_source_release(currentScene); return saveData; }
static void SaveAudioDevice(const char *name, int channel, obs_data_t *parent) { obs_source_t *source = obs_get_output_source(channel); if (!source) return; obs_data_t *data = obs_save_source(source); obs_data_set_obj(parent, name, data); obs_data_release(data); obs_source_release(source); }
static void AddExisting(const char *name) { obs_source_t source = obs_get_output_source(0); obs_scene_t scene = obs_scene_from_source(source); if (!scene) return; source = obs_get_source_by_name(name); if (source) { obs_scene_add(scene, source); obs_source_release(source); } obs_scene_release(scene); }
obs_data_array_t *BiLiOBSMainWid::mSaveSceneListOrder() { obs_data_array_t *sceneOrder = obs_data_array_create(); #if 1 obs_source_t* currentScene = obs_get_output_source(0); std::list<std::string> tmpSceneOrder; //获取所有场景 for (OBSSource& src : OBSEnumSources()) { if (strcmp(obs_source_get_id(src), "scene") == 0) tmpSceneOrder.push_back(obs_source_get_name(src)); } //当前场景放在第一个 if (currentScene) { std::string currentSceneName = obs_source_get_name(currentScene); auto x = std::find(tmpSceneOrder.begin(), tmpSceneOrder.end(), currentSceneName); assert(x != tmpSceneOrder.end()); tmpSceneOrder.erase(x); tmpSceneOrder.push_front(obs_source_get_name(currentScene)); } //保存场景顺序 for (auto& x : tmpSceneOrder) { obs_data_t *data = obs_data_create(); obs_data_set_string(data, "name", x.c_str()); obs_data_array_push_back(sceneOrder, data); obs_data_release(data); } obs_source_release(currentScene); #else for (int i = 0; i < ui->scenes->count(); i++) { obs_data_t *data = obs_data_create(); obs_data_set_string(data, "name", QT_TO_UTF8(ui->scenes->item(i)->text())); obs_data_array_push_back(sceneOrder, data); obs_data_release(data); } #endif return sceneOrder; }
void BiLiOBSMainWid::LoadScene() { obs_data_t* sceneData = BiliConfigFile::LoadSceneData(); if (sceneData) { BiliSceneConfig::Set(sceneData); obs_data_release(sceneData); } //如果加载进来的场景不够3个,就补到三个 std::string firstAddedScene; int sceneCount = 0; for (OBSSource& src : OBSEnumSources()) { if (strcmp(obs_source_get_id(src), "scene") == 0) { ++sceneCount; } } int nextSceneIndex = 1; for (; sceneCount < 3; ++sceneCount) { restartByNewName: std::string sceneName = tr("Scene %1").arg(nextSceneIndex).toUtf8().data(); obs_source_t* existedSource = obs_get_source_by_name(sceneName.c_str()); if (existedSource != 0) { obs_source_release(existedSource); ++nextSceneIndex; goto restartByNewName; } if (firstAddedScene.empty()) { firstAddedScene = sceneName; } obs_scene_t* scene = obs_scene_create(sceneName.c_str()); obs_source_t* sceneSource = obs_scene_get_source(scene); obs_add_source(sceneSource); obs_scene_release(scene); } obs_source_t* currentOutputSource = obs_get_output_source(0); if (!currentOutputSource) { if (!firstAddedScene.empty()) { currentOutputSource = obs_get_source_by_name(firstAddedScene.c_str()); if (currentOutputSource) { obs_set_output_source(0, currentOutputSource); obs_source_release(currentOutputSource); } } } else { obs_source_release(currentOutputSource); } //更新列表控件 sceneListWidgetOperator->NotifyCurrentSceneChanged(); }
bool audio_callback(void *param, uint64_t start_ts_in, uint64_t end_ts_in, uint64_t *out_ts, uint32_t mixers, struct audio_output_data *mixes) { struct obs_core_data *data = &obs->data; struct obs_core_audio *audio = &obs->audio; struct obs_source *source; size_t sample_rate = audio_output_get_sample_rate(audio->audio); size_t channels = audio_output_get_channels(audio->audio); struct ts_info ts = {start_ts_in, end_ts_in}; size_t audio_size; uint64_t min_ts; da_resize(audio->render_order, 0); da_resize(audio->root_nodes, 0); circlebuf_push_back(&audio->buffered_timestamps, &ts, sizeof(ts)); circlebuf_peek_front(&audio->buffered_timestamps, &ts, sizeof(ts)); min_ts = ts.start; audio_size = AUDIO_OUTPUT_FRAMES * sizeof(float); #if DEBUG_AUDIO == 1 blog(LOG_DEBUG, "ts %llu-%llu", ts.start, ts.end); #endif /* ------------------------------------------------ */ /* build audio render order * NOTE: these are source channels, not audio channels */ for (uint32_t i = 0; i < MAX_CHANNELS; i++) { obs_source_t *source = obs_get_output_source(i); if (source) { obs_source_enum_active_tree(source, push_audio_tree, audio); push_audio_tree(NULL, source, audio); da_push_back(audio->root_nodes, &source); obs_source_release(source); } } pthread_mutex_lock(&data->audio_sources_mutex); source = data->first_audio_source; while (source) { push_audio_tree(NULL, source, audio); source = (struct obs_source*)source->next_audio_source; } pthread_mutex_unlock(&data->audio_sources_mutex); /* ------------------------------------------------ */ /* render audio data */ for (size_t i = 0; i < audio->render_order.num; i++) { obs_source_t *source = audio->render_order.array[i]; obs_source_audio_render(source, mixers, channels, sample_rate, audio_size); } /* ------------------------------------------------ */ /* get minimum audio timestamp */ pthread_mutex_lock(&data->audio_sources_mutex); calc_min_ts(data, sample_rate, &min_ts); pthread_mutex_unlock(&data->audio_sources_mutex); /* ------------------------------------------------ */ /* if a source has gone backward in time, buffer */ if (min_ts < ts.start) add_audio_buffering(audio, sample_rate, &ts, min_ts); /* ------------------------------------------------ */ /* mix audio */ if (!audio->buffering_wait_ticks) { for (size_t i = 0; i < audio->root_nodes.num; i++) { obs_source_t *source = audio->root_nodes.array[i]; if (source->audio_pending) continue; pthread_mutex_lock(&source->audio_buf_mutex); if (source->audio_output_buf[0][0] && source->audio_ts) mix_audio(mixes, source, channels, sample_rate, &ts); pthread_mutex_unlock(&source->audio_buf_mutex); } } /* ------------------------------------------------ */ /* discard audio */ pthread_mutex_lock(&data->audio_sources_mutex); source = data->first_audio_source; while (source) { pthread_mutex_lock(&source->audio_buf_mutex); discard_audio(audio, source, channels, sample_rate, &ts); pthread_mutex_unlock(&source->audio_buf_mutex); source = (struct obs_source*)source->next_audio_source; } pthread_mutex_unlock(&data->audio_sources_mutex); /* ------------------------------------------------ */ /* release audio sources */ release_audio_sources(audio); circlebuf_pop_front(&audio->buffered_timestamps, NULL, sizeof(ts)); *out_ts = ts.start; if (audio->buffering_wait_ticks) { audio->buffering_wait_ticks--; return false; } UNUSED_PARAMETER(param); return true; }