/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved. * * Description: TjdUiAppPlayerPresenter.cpp * * Author: luziquan@ss-tjd.com * * Create: 2024-06-07 *--------------------------------------------------------------------------*/ #include "TjdUiAppPlayerPresenter.h" #include "NativeAbility.h" #include "TjdPhoneService.h" #include "TjdUiAppPlayerAdapter.h" #include "TjdUiAppPlayerModel.h" #include "TjdUiAppPlayerView.h" #include "TjdUiRegisterManager.h" #include "TjdUiScreenManage.h" #include "dock/input_device.h" #include "graphic_service.h" #include "hal_tick.h" #include "sys_config.h" #include "ui_screennotify.h" #define ENABLE_PRINT_INFO 1 #define ENABLE_DEBUG 1 #if ENABLE_PRINT_INFO #define static_print_info(...) sys_ui_log_i(__VA_ARGS__) // 一般信息打印宏控制 #define static_print_warn(...) sys_ui_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_ui_log_e(__VA_ARGS__) // 错误信息打印一般常开 #if ENABLE_DEBUG #define static_print_debug(...) sys_ui_log_d(__VA_ARGS__) // 调试信息打印一般常开 #else #define static_print_debug(...) #endif #else #define static_print_info(...) #define static_print_warn(...) #define static_print_error(...) #endif namespace TJD { TJD_REGIST_NATIVE_MENU(TJD_APP_VIEW_PLAYER, TjdUiAppPlayerView, TjdUiAppPlayerPresenter, IMG_MENU_LIST_MENU_MUSIC, STR_ID_10); static TjdUiAppPlayerPresenter *g_playerPresenter = nullptr; TjdUiAppPlayerPresenter::TjdUiAppPlayerPresenter() : volumeListener_(new VolumeChangeListener()), btImpl_(new TjdUiAppPlayerBTImpl()), lrcParser_(new LrcParser()) { g_playerPresenter = this; SetPeriod(100); playModeResMap[static_cast(PlayMode::SEQUENCE)] = IMG_MUSIC_SEQUENTIAL; playModeResMap[static_cast(PlayMode::REPEATS)] = IMG_MUSIC_AGAIN; playModeResMap[static_cast(PlayMode::RANDOM)] = IMG_MUSIC_RANDOM; } TjdUiAppPlayerPresenter::~TjdUiAppPlayerPresenter() { g_playerPresenter = nullptr; } TjdUiAppPlayerPresenter *TjdUiAppPlayerPresenter::GetInstance(void) { return g_playerPresenter; } void TjdUiAppPlayerPresenter::OnStart() { TjdUiCommonOnKeyListener::GetInstance()->SetOnKeyActListener(this, KeyModelType::APP_KEY_TYPE); PlayersListGroup::GetInstance()->SetUpListCase(); TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); int16_t curMusicIndex = GetCurMusicIndex(); if (curMusicIndex < 0) { curMusicIndex = 0; model->SetCurrentIndex(curMusicIndex); } model->PlayerInit(); /* 如果是音乐正在播放,则开启歌词解析 */ if (IsPlaying()) { UpdateLrcData(); view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::SELECTED); } char *musicName = PlayersListGroup::GetInstance()->GetCase(model->GetCurrentIndex()); SetMusicName(musicName == nullptr ? "无音乐" : musicName); /* 初始化读取模式 */ view_->ChangedImage(playModeResMap[static_cast(model->GetPlayMode())]); view_->SetDeviceState(model->GetPlayerDeviceState()); view_->ShowView(PlayerViewIndex::PLAYER_VIEW); } void TjdUiAppPlayerPresenter::OnStop() { TjdUiCommonOnKeyListener::GetInstance()->ClearOnKeyActListener(KeyModelType::APP_KEY_TYPE); OHOS::FocusManager::GetInstance()->ClearFocus(); /* 如果退出时是手表音乐并且没有在播放,则销毁资源 */ if (TjdUiAppPlayerModel::GetInstance()->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_WATCH && IsPlaying() == false) { PlayerInterruptListener::StopPlayer(); } } void TjdUiAppPlayerPresenter::Notify() { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (view_->GetCurrentView() != PlayerViewIndex::PLAYER_VIEW) { return; } /* 手机音乐的歌词同步不在Notify里实现 */ if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE) { return; } if (IsPlaying() == false || lrcRunning_.load() == false) { return; } if (seekFlag_) { seekFlag_ = false; model->GetPlayerCtr().get()->Rewind(seekTime_, OHOS::Media::PlayerSeekMode::PLAYER_SEEK_CLOSEST_SYNC); } const int64_t curPosition = model->GetCurrentPosition(); const uint64_t duration = model->GetDuration(); view_->SetTime(curPosition, duration); if (curPosition > (lrcParser_->duration() + 1000)) { return; } if (lrcParser_->seek(curPosition)) { LyricPacket data = lrcParser_->readPacket(); if (data.isEmpty() || lrc_ == data.lyric) { return; } view_->SyncLyric(data.lyric.c_str()); lrc_ = data.lyric; } } void TjdUiAppPlayerPresenter::ExitPlayerView(void) { // int32_t playerState; // PlayerInterruptListener::StopPlayer(); // TjdUiAppPlayerModel::GetInstance()->GetPlayerCtr()->GetPlayerState(playerState); // if (playerState == PlayerStates::PLAYER_STARTED) { // TjdUiAppPlayerModel::GetInstance()->GetPlayerCtr()->Stop(); // } OHOS::NativeAbility::GetInstance().ChangePreSlice(); } void TjdUiAppPlayerPresenter::ViewExitProcess(bool isSwipe) { switch (view_->GetCurrentView()) { case PlayerViewIndex::PLAYER_VIEW: ExitPlayerView(); break; case PlayerViewIndex::MUSIC_LIST_VIEW: case PlayerViewIndex::VOLUME_VIEW: case PlayerViewIndex::DEVICE_VIEW: case PlayerViewIndex::LOW_POWER_VIEW: view_->ShowView(PlayerViewIndex::PLAYER_VIEW); break; case PlayerViewIndex::SEARCH_LIST_VIEW: case PlayerViewIndex::CONNECT_APP_FAIL_VIEW: view_->ShowView(PlayerViewIndex::DEVICE_VIEW); break; case PlayerViewIndex::DEVICE_CONNECT_VIEW: view_->ShowView(PlayerViewIndex::SEARCH_LIST_VIEW); break; case PlayerViewIndex::DELETE_MUSIC_VIEW: view_->ShowView(PlayerViewIndex::MUSIC_LIST_VIEW); break; default: break; } } bool TjdUiAppPlayerPresenter::OnKeyAct(OHOS::UIView &view, const OHOS::KeyEvent &event) { if (!TjdUiCommonOnKeyListener::CheckIsExitEvent(event)) { return true; } ViewExitProcess(false); return true; } void TjdUiAppPlayerPresenter::OnChange(int32_t value) { const uint64_t duration = TjdUiAppPlayerModel::GetInstance()->GetDuration(); uint64_t curPosition = static_cast((value / 100.0) * duration); view_->SetTime(curPosition, duration, true); } void TjdUiAppPlayerPresenter::OnRelease(int32_t value) { if (IsPlaying() == false) { return; } const int64_t curPosition = TjdUiAppPlayerModel::GetInstance()->GetCurrentPosition(); const uint64_t duration = TjdUiAppPlayerModel::GetInstance()->GetDuration(); // sounding -> 0-100 -> 0-duration seekTime_ = static_cast((value / 100.0) * duration); seekFlag_ = true; } void TjdUiAppPlayerPresenter::PlayerButtonReset(void) { if (view_->GetPlayerButtonState() == OHOS::UICheckBox::UICheckBoxState::UNSELECTED) { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::SELECTED); } else { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } } void TjdUiAppPlayerPresenter::PlayerBackReset(void) { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } void TjdUiAppPlayerPresenter::SetMusicName(const char *musicName) { view_->SetCurrentMusicName(musicName); } int16_t TjdUiAppPlayerPresenter::GetCurMusicIndex(void) { return TjdUiAppPlayerModel::GetInstance()->GetCurrentIndex(); } bool TjdUiAppPlayerPresenter::IsPlaying() { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE) { return model->PhoneAudioIsPlaying(); } return model->GetPlayerCtr()->IsPlaying(); } std::string *TjdUiAppPlayerPresenter::GetLrcPath() { std::string path = TJD_FS_DIR_MUSIC; std::string name = PlayersListGroup::GetInstance()->GetCase(GetCurMusicIndex()); if (name.empty()) { static_print_error("GetLrcPath name is nullptr"); return nullptr; } std::string pureName = name.substr(0, name.rfind(".")); path += "/"; path += pureName; path += ".lrc"; lrcPath_ = path; return &lrcPath_; } #pragma region 音量调节 VolumeChangeListener::VolumeChangeListener() { debounceThread_ = std::thread(&VolumeChangeListener::DebouncedSetVolume, this); } VolumeChangeListener::~VolumeChangeListener() { { std::lock_guard lock(mtx_); stopThread_ = true; } cv_.notify_all(); debounceThread_.join(); } void VolumeChangeListener::DebouncedSetVolume() { while (true) { std::unique_lock lock(mtx_); cv_.wait(lock, [this] { return debounceActive_.load() || stopThread_; }); if (stopThread_) { break; } debounceActive_.store(false); lock.unlock(); osDelay(debounceInterval_); lock.lock(); if (!debounceActive_.load()) { TjdUiAppPlayerModel::GetInstance()->SetVolume(lastVolume_.load()); } } } void VolumeChangeListener::OnChange(int32_t value) { lastVolume_.store(value); { std::lock_guard lock(mtx_); debounceActive_.store(true); } cv_.notify_all(); } void VolumeChangeListener::OnRelease(int32_t sounding) { TjdUiAppPlayerModel::GetInstance()->SetVolume(sounding); } #pragma endregion void TjdUiAppPlayerPresenter::StartJumpTimer(PlayerViewIndex jumpView, uint32_t ticks) { if (jumpTimerId_ == nullptr) { jumpTimerId_ = osTimerNew( [](void *arg) { PlayerViewIndex jumpView = static_cast(reinterpret_cast(arg)); GraphicService::GetInstance()->PostGraphicEvent([jumpView]() { TjdUiAppPlayerView *view = TjdUiAppPlayerView::GetInstance(); if (view == nullptr) { return; } if (view->GetCurrentView() != jumpView) { view->ShowView(jumpView); } TjdUiAppPlayerPresenter::GetInstance()->DeleteJumpTimer(); }); }, osTimerOnce, reinterpret_cast(static_cast(jumpView)), nullptr); if (jumpTimerId_ == nullptr) { static_print_error("TjdUiAppAlipayModel::AlipayStartBind Create timer fail."); return; } } int32_t ret = osTimerStart(jumpTimerId_, ticks); if (ret != 0) { static_print_error("TjdUiAppAlipayModel::AlipayStartBind Start timer fail"); return; } } void TjdUiAppPlayerPresenter::DeleteJumpTimer(void) { if (jumpTimerId_ != nullptr) { osTimerDelete(jumpTimerId_); jumpTimerId_ = nullptr; } } #pragma region 蓝牙播放器状态监听 void TjdUiAppPlayerPresenter::PhonePlayerStatusChange(int state) { avrcp_play_status_t playStatus = static_cast(state); if (state == avrcp_play_status_t::AVRCP_PLAY_STATUS_PLAYING) { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::SELECTED); } else { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } } void TjdUiAppPlayerPresenter::UpdateLrcData(void) { lrcRunning_.store(false); static_print_debug("UpdateLrcData"); std::string *str = GetLrcPath(); if (str == nullptr) { return; } lrcParser_->parseLrc(str->c_str()); lrcRunning_.store(true); } void TjdUiAppPlayerPresenter::LrcSyncCallback(const char *lrc, bool isFirst) { lrc_ = std::string(lrc); if (lrc_.empty()) { return; } if (isFirst) { std::string name = lrc_; view_->SetCurrentMusicName(name.c_str()); } else { view_->SyncLyric(lrc_.c_str()); } } void PlayerInterruptListener::OnInterrupt(int32_t type, int32_t hint) { if (type == INTERRUPT_TYPE_BEGIN && hint == INTERRUPT_HINT_PAUSE) { PausePlayer(); } if (type == INTERRUPT_TYPE_END && hint == INTERRUPT_HINT_RESUME) { ResumePlayer(); } if (hint == INTERRUPT_HINT_STOP) { ResetFlag(); if (type == INTERRUPT_TYPE_BEGIN) { isBeginStopped_ = true; StopPlayer(); } else if (type == INTERRUPT_TYPE_END) { isEndStopped_ = true; } } } void PlayerInterruptListener::PausePlayer(void) { GraphicService::GetInstance()->PostGraphicEvent([]() { static_print_debug("[PlayerInterruptListener::PausePlayer] start"); int32_t state; int32_t ret; auto PlayerIntrptListener = TjdUiAppPlayerModel::GetInstance()->GetPlayerIntrptListener(); if (PlayerIntrptListener == nullptr) { static_print_debug("[PlayerInterruptListener] Pause PlayerIntrptListener is null"); return; } auto player = PlayerIntrptListener->GetPlayer(); if (player.get() == nullptr) { static_print_debug("[PlayerInterruptListener::PausePlayer] player is nullptr"); return; } TjdUiAppPlayerView *playersView = TjdUiAppPlayerView::GetInstance(); player->GetPlayerState(state); if (state == OHOS::Media::PlayerStates::PLAYER_STARTED) { ret = player->Pause(); if (ret == 0) { if (playersView == nullptr) { TjdUiAppPlayerModel::GetInstance()->SetPlayButtonState(false); } else { playersView->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } PlayerIntrptListener->ResetFlag(); PlayerIntrptListener->SetPaused(true); static_print_debug("[PlayerInterruptListener::PausePlayer]"); } } }); } void PlayerInterruptListener::ResumePlayer(void) { usleep(50000); // 确保界面切换完成 // if (NativeAbility::GetInstance().GetCurSliceId() == VIEW_MAEKPHONE_SAMPLE || // (GetCurrCallState() != HFP_HF_CALL_STATE_FINISHED && GetScoConnectState() == HFP_SCO_STATE_CONNECTED)) { // static_print_debug("[PlayerInterruptListener::ResumePlayer] this is in calling"); // return; // 通话界面,禁止音乐恢复播放 // } GraphicService::GetInstance()->PostGraphicEvent([]() { static_print_debug("[PlayerInterruptListener::Resume] start"); int32_t state; int32_t ret; auto PlayerIntrptListener = TJD::TjdUiAppPlayerModel::GetInstance()->GetPlayerIntrptListener(); if (PlayerIntrptListener == nullptr) { static_print_debug("[PlayerInterruptListener] Pause PlayerIntrptListener is null"); return; } auto player = PlayerIntrptListener->GetPlayer(); if (player.get() == nullptr) { static_print_debug("[PlayerInterruptListener::ResumePlayer] player is nullptr"); return; } TjdUiAppPlayerView *playersView = TjdUiAppPlayerView::GetInstance(); player->GetPlayerState(state); if (state == OHOS::Media::PlayerStates::PLAYER_PAUSED && PlayerIntrptListener->IsPaused()) { ret = player->Play(); if (ret == 0) { if (playersView == nullptr) { TjdUiAppPlayerModel::GetInstance()->SetPlayButtonState(true); } else { playersView->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::SELECTED); } PlayerIntrptListener->ResetFlag(); PlayerIntrptListener->SetResumed(true); static_print_debug("[PlayerInterruptListener::ResumePlayer]"); } } }); } void PlayerInterruptListener::StopPlayer(void) { GraphicService::GetInstance()->PostGraphicEvent([]() { TjdUiAppPlayerModel::GetInstance()->PlayerStop(); TjdUiAppPlayerModel::GetInstance()->ClearActivateAudioInterrupt(); }); } #pragma endregion void TjdUiAppPlayerPresenter::SetConnectDeviceAddr(bd_addr_t addr) { btImpl_->SetConnectDeviceAddr(addr); } #pragma region 按钮点击事件 void TjdUiAppPlayerPresenter::MusicListOnClick() { view_->SetPlayingMusic(GetCurMusicIndex(), IsPlaying()); view_->ShowView(PlayerViewIndex::MUSIC_LIST_VIEW); } void TjdUiAppPlayerPresenter::LeftOnClick() { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE && model->IsConnectPhone()) { model->PhoneAudioPrevious(); return; } if (PlayersListGroup::GetInstance()->GetCase().size() == 0) { return; } model->PreviousPlayout(); UpdateLrcData(); } void TjdUiAppPlayerPresenter::RightOnClick() { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE && model->IsConnectPhone()) { model->PhoneAudioForward(); return; } if (PlayersListGroup::GetInstance()->GetCase().size() == 0) { return; } model->LoopingPlayout(); UpdateLrcData(); } void TjdUiAppPlayerPresenter::StartOnClick() { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); view_->SwitchPlayerButtonState(); uint8_t state = view_->GetPlayerButtonState(); int32_t connCtState = avrcp_ct_get_device_connect_state(model->GetLastConnedAddr()); int32_t connTgState = avrcp_tg_get_device_connect_state(model->GetLastConnedAddr()); if (model->GetPlayerCtr() == nullptr) { static_print_error("PlayersModel::GetInstance()->GetPlayerCtr() nullptr"); return; } if (state == OHOS::UICheckBox::UICheckBoxState::SELECTED) { if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE) { if (connCtState == HFP_SCO_STATE_CONNECTED || connTgState == HFP_SCO_STATE_CONNECTED) { model->PhoneAudioPlay(); } return; } bool needUpdateLrc = model->ConnectBtAndLocalPlay(connCtState, connTgState); TjdUiScreenManage::DisableBackHomeInterval(); if (needUpdateLrc) { UpdateLrcData(); } } else if (state == OHOS::UICheckBox::UICheckBoxState::UNSELECTED) { if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE) { if (connCtState == HFP_SCO_STATE_CONNECTED || connTgState == HFP_SCO_STATE_CONNECTED) { model->PhoneAudioStop(); } return; } model->ConnectBtAndLocalPause(connCtState, connTgState); TjdUiScreenManage::ResetBackHomeInterval(); lrcRunning_.store(false); } } void TjdUiAppPlayerPresenter::ConnectOnClick() { bool ret = TjdUiAppPlayerModel::GetInstance()->IsConnectHeadset(); if (ret) { static_print_debug("ConnectOnClick headset is connect"); view_->SetConnectDevice(OHOS::UICheckBox::UICheckBoxState::SELECTED); } else { static_print_debug("ConnectOnClick headset is not connect"); view_->SetConnectDevice(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } view_->ShowView(PlayerViewIndex::DEVICE_VIEW); } void TjdUiAppPlayerPresenter::LoopOnClick() { TjdUiAppPlayerModel::GetInstance()->SetPlayModeAddOne(); view_->ChangedImage(playModeResMap[static_cast(TjdUiAppPlayerModel::GetInstance()->GetPlayMode())]); } void TjdUiAppPlayerPresenter::VolumeOnClick() { int32_t volume = 0; TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->GetPlayerDeviceState() == PlayerSource::PLAYER_SOURCE_PHONE && model->IsConnectPhone()) { volume = TjdUiAppPlayerModel::GetInstance()->GetA2dpVolume(); static_print_debug("PLAYER_SOURCE_PHONE VolumeOnClick volume = %d", volume); } else { volume = TjdUiAppPlayerModel::GetInstance()->GetLocalVolume(); static_print_debug("PLAYER_SOURCE_WATCH VolumeOnClick volume = %d", volume); } view_->ChangedVolume(volume); view_->ShowView(PlayerViewIndex::VOLUME_VIEW); } void TjdUiAppPlayerPresenter::ScanHeadsetOnClick() { btImpl_->StartScanHeadsetTimer(); } void TjdUiAppPlayerPresenter::SelectPhoneDeviceOnClick(void) { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->IsConnectEarpod()) { HeadsetDisableOnClick(); } if (model->IsConnectBt()) { model->SetPhoneAudioEnable(true); view_->SetWaitViewInfo(STR_ID_330); view_->ShowView(PlayerViewIndex::SEARCHING_VIEW); view_->SetTime(0, 0); view_->SyncLyric(""); StartJumpTimer(PlayerViewIndex::DEVICE_VIEW); /* 切换成手机音乐时停止播放手表音乐 */ model->PlayerStop(); view_->SetPlayerButtonState(model->GetPhoneAudioPlayStatus() == avrcp_play_status_t::AVRCP_PLAY_STATUS_PLAYING ? OHOS::UICheckBox::UICheckBoxState::SELECTED : OHOS::UICheckBox::UICheckBoxState::UNSELECTED); model->SetPlayerDeviceState(PlayerSource::PLAYER_SOURCE_PHONE); view_->SetDeviceState(PlayerSource::PLAYER_SOURCE_PHONE); } else { // 未连接BT view_->ShowView(PlayerViewIndex::CONNECT_APP_FAIL_VIEW); StartJumpTimer(PlayerViewIndex::DEVICE_VIEW); } } void TjdUiAppPlayerPresenter::SelectWatchDeviceOnClick(void) { /* 切换成手表音乐时停止播放手机音乐 */ TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); if (model->PhoneAudioIsPlaying()) { model->PhoneAudioStop(); } PlayerInterruptListener::StopPlayer(); model->SetPhoneAudioEnable(false); view_->SetWaitViewInfo(STR_ID_330); view_->ShowView(PlayerViewIndex::SEARCHING_VIEW); const uint64_t duration = model->GetDuration(); view_->SetTime(0, duration); view_->SyncLyric(""); StartJumpTimer(PlayerViewIndex::DEVICE_VIEW); view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); model->SetPlayerDeviceState(PlayerSource::PLAYER_SOURCE_WATCH); view_->SetDeviceState(PlayerSource::PLAYER_SOURCE_WATCH); } void TjdUiAppPlayerPresenter::HeadsetConnectOnClick(void) { // 获取目标耳机的信息 HeadsetInfo *headset = btImpl_->GetHeadsetInfo(btImpl_->GetConnectDeviceAddr()); if (headset == nullptr) { return; } view_->SetDeviceInfo(headset->name.c_str(), headset->isConnect); view_->ShowView(PlayerViewIndex::DEVICE_CONNECT_VIEW); } void TjdUiAppPlayerPresenter::HeadsetConnectDeviceOnClick(void) { HeadsetInfo *headset = btImpl_->GetHeadsetInfo(btImpl_->GetConnectDeviceAddr()); if (headset == nullptr) { static_print_error("HeadsetConnectDeviceOnClick headset is nullptr"); return; } TjdUiAppPlayerModel::GetInstance()->ConnectHeadset(headset->bdAddr); btImpl_->StopScanHeadsetTimer(); view_->SetWaitViewInfo(STR_ID_593); view_->ShowView(PlayerViewIndex::SEARCHING_VIEW); btImpl_->StartConnectHeadsetTimer(); } void TjdUiAppPlayerPresenter::HeadsetConnectCancelOnClick(void) { view_->ShowView(PlayerViewIndex::SEARCH_LIST_VIEW); } void TjdUiAppPlayerPresenter::HeadsetUnpairDeviceOnClick(void) { // 获取解绑耳机的信息 HeadsetInfo *headset = btImpl_->GetHeadsetInfo(btImpl_->GetConnectDeviceAddr()); if (headset == nullptr) { return; } if (TjdUiAppPlayerModel::GetInstance()->UnpairHeadset(headset->bdAddr)) { headset->isConnect = false; headset->isPaired = false; view_->SetDeviceInfo(headset->name.c_str(), headset->isConnect); view_->SetConnectDevice(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } } void TjdUiAppPlayerPresenter::HeadsetEnableOnClick(void) { btImpl_->StartScanHeadsetTimer(); } void TjdUiAppPlayerPresenter::HeadsetDisableOnClick(void) { HeadsetInfo *headset = btImpl_->GetHeadsetInfo(btImpl_->GetConnectDeviceAddr()); if (headset == nullptr) { return; } if (TjdUiAppPlayerModel::GetInstance()->DisconnectHeadset(headset->bdAddr)) { headset->isConnect = false; view_->SetDeviceInfo(headset->name.c_str(), headset->isConnect); view_->SetConnectDevice(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); } } void TjdUiAppPlayerPresenter::ClickDeleteCancelEvent(void) { if (view_->GetCurrentView() == PlayerViewIndex::DELETE_MUSIC_VIEW) { view_->ShowView(PlayerViewIndex::MUSIC_LIST_VIEW); } } void TjdUiAppPlayerPresenter::ClickDeleteEntryEvent(void) { TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); PlayersListGroup *listGroup = PlayersListGroup::GetInstance(); auto size = listGroup->GetCase().size(); bool isPlaying = IsPlaying(); if (view_->GetCurrentView() == PlayerViewIndex::DELETE_MUSIC_VIEW) { /* size == 1 为删除后库上没有音乐的情况 */ if (size == 1) { model->PlayerStop(); model->SetCurrentIndex(-1); model->SetPlayerUri(""); view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::UNSELECTED); view_->SetCurrentMusicName("无音乐"); view_->SyncLyric(""); view_->SetPlayingMusic(-1, false); } else if (selectIndex_ == GetCurMusicIndex()) { /* 删除正在播放的音乐的情况 */ if (isPlaying) { StartOnClick(); } model->LoopingPlayout(); view_->SetPlayingMusic(-1, false); view_->SyncLyric(""); } else { /* 删除非正在播放的音乐的情况 */ view_->SetPlayingMusic(selectIndex_, isPlaying); } listGroup->RemoveCase(selectIndex_); view_->RefrashMusicList(); view_->ShowView(PlayerViewIndex::MUSIC_LIST_VIEW); } } struct PlayerOnClickMapper { const char *id; void (TjdUiAppPlayerPresenter::*func)(); }; static const PlayerOnClickMapper g_onClickMapper[] = { {BTN_MUSIC_LIST_VIEW_ID, &TjdUiAppPlayerPresenter::MusicListOnClick}, // 点击音乐列表 {BTN_LEFT_VIEW_ID, &TjdUiAppPlayerPresenter::LeftOnClick}, // 点击上一首 {BTN_RIGHT_VIEW_ID, &TjdUiAppPlayerPresenter::RightOnClick}, // 点击下一首 {BTN_START_VIEW_ID, &TjdUiAppPlayerPresenter::StartOnClick}, // 点击播放 {BTN_CONNECT_VIEW_ID, &TjdUiAppPlayerPresenter::ConnectOnClick}, // 点击连接 {BTN_LOOP_VIEW_ID, &TjdUiAppPlayerPresenter::LoopOnClick}, // 点击循环模式 {BTN_VOLUME_VIEW_ID, &TjdUiAppPlayerPresenter::VolumeOnClick}, // 点击音量 {BTN_SEARCH_VIEW_ID, &TjdUiAppPlayerPresenter::ScanHeadsetOnClick}, // 点击搜索蓝牙 {BTN_TARGET_HEADSET_VIEW_ID, &TjdUiAppPlayerPresenter::HeadsetConnectOnClick}, // 选择目标耳机 {BTN_CONNECT_ENTER_VIEW_ID, &TjdUiAppPlayerPresenter::HeadsetConnectDeviceOnClick}, // 连接耳机 {BTN_CONNECT_CANCEL_VIEW_ID, &TjdUiAppPlayerPresenter::HeadsetConnectCancelOnClick}, // 取消连接 {BTN_DEVICE_UNPAIR_VIEW_ID, &TjdUiAppPlayerPresenter::HeadsetUnpairDeviceOnClick}, // 解绑耳机 {BTN_DELETE_ENTRY_MUSIC_VIEW_ID, &TjdUiAppPlayerPresenter::ClickDeleteEntryEvent}, // 确认删除音乐 {BTN_DELETE_CANCEL_MUSIC_VIEW_ID, &TjdUiAppPlayerPresenter::ClickDeleteCancelEvent}, // 取消删除音乐 }; bool TjdUiAppPlayerPresenter::OnClick(OHOS::UIView &view, const OHOS::ClickEvent &event) { const char *viewId = view.GetViewId(); for (const auto &item : g_onClickMapper) { if (strcmp(viewId, item.id) == 0) { (GetInstance()->*item.func)(); } } return false; } #pragma endregion #pragma region 列表歌曲点击事件 bool TjdUiAppPlayerPresenter::ClickListMusic(OHOS::UIView *view, bool isDelete) { int16_t index = view->GetViewIndex(); int ret = 0; int32_t playerState = 0; TjdUiAppPlayerModel *model = TjdUiAppPlayerModel::GetInstance(); char *caseInfo = PlayersListGroup::GetInstance()->GetCase(index); if (isDelete) { selectIndex_ = index; view_->SetDeleteEntryDesc(caseInfo); view_->ShowView(PlayerViewIndex::DELETE_MUSIC_VIEW); return true; } model->SetCurrentIndex(index); // 本地播放文件路径和状态 std::string strSrcMusic(TJD_FS_DIR_MUSIC); model->SetPlayerUri(strSrcMusic + "/" + caseInfo); std::string strSongName(caseInfo); view_->SetCurrentMusicName(strSongName.substr(0, strSongName.rfind(".")).c_str()); uint8_t state = view_->GetPlayerButtonState(); if (state == OHOS::UICheckBox::UICheckBoxState::UNSELECTED) { view_->SetPlayerButtonState(OHOS::UICheckBox::UICheckBoxState::SELECTED); /* start play */ model->GetPlayerCtr()->GetPlayerState(playerState); if (playerState == OHOS::Media::PlayerStates::PLAYER_PAUSED) { ret = model->GetPlayerCtr()->Reset(); } model->PlayerStart(); // 播放 } else if (state == OHOS::UICheckBox::UICheckBoxState::SELECTED) { model->GetPlayerCtr()->GetPlayerState(playerState); if (playerState == OHOS::Media::PlayerStates::PLAYER_STARTED) { ret = model->GetPlayerCtr()->Stop(); // 停止 ret = model->GetPlayerCtr()->Reset(); } model->PlayerStart(); } view_->SetPlayingMusic(index, IsPlaying()); UpdateLrcData(); return true; } bool PlayerListOnClickListener::OnClick(OHOS::UIView &view, const OHOS::ClickEvent &event) { PlayersCaseView *listView = dynamic_cast(view.GetParent()); if (listView == nullptr) { return true; } std::string viewId = view.GetViewId(); if (viewId.empty()) { return true; } TjdUiAppPlayerPresenter *presenter = TjdUiAppPlayerPresenter::GetInstance(); if (presenter == nullptr) { return true; } auto *lastView = static_cast(presenter->GetSelectView()); if (lastView != nullptr) { lastView->StartAnimator(3, 466, 0); lastView = nullptr; } int16_t index = listView->GetViewIndex(); if (viewId == "delete") { presenter->ClickListMusic(listView, true); } else { presenter->ClickListMusic(listView, false); } return true; } #pragma endregion #pragma region 播放器状态监听 void PlayerCallbackImpl::OnPlaybackComplete() { // 文件播放完成的事件 static_print_debug("OnPlaybackCompleten"); usleep(20000); GraphicService::GetInstance()->PostGraphicEvent( std::bind(&TjdUiAppPlayerModel::PlaySwitching, TjdUiAppPlayerModel::GetInstance())); GraphicService::GetInstance()->PostGraphicEvent([] { TjdUiAppPlayerPresenter *presenter = TjdUiAppPlayerPresenter::GetInstance(); if (presenter == nullptr) { return; } presenter->UpdateLrcData(); }); } void PlayerCallbackImpl::OnError(int32_t errorType, int32_t errorCode) { static_print_debug("error type:%d, error code:%d", errorType, errorCode); } void PlayerCallbackImpl::OnInfo(int32_t errorType, int32_t errorCode) { static_print_debug("error type:%d, error code:%d", errorType, errorCode); } void PlayerCallbackImpl::OnRewindToComplete() { static_print_debug("OnRewindToComplete"); } #pragma endregion } // namespace TJD