bool OMXPlayerVideo::Open( COMXStreamInfo &hints, OMXClock *av_clock, uint& textureId, bool deinterlace, bool mpeg, bool hdmi_clock_sync, bool use_thread, float display_aspect ) { if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; if(ThreadHandle()) Close(); m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_fps = 25.0f; m_frametime = 0; m_Deinterlace = deinterlace; m_display_aspect = display_aspect; m_bMpeg = mpeg; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_use_thread = use_thread; m_flush = false; m_cached_size = 0; m_iVideoDelay = 0; m_hdmi_clock_sync = hdmi_clock_sync; m_pts = 0; m_syncclock = true; m_speed = DVD_PLAYSPEED_NORMAL; m_iSubtitleDelay = 0; m_pSubtitleCodec = NULL; m_FlipTimeStamp = m_av_clock->GetAbsoluteClock(); if(!OpenDecoder(textureId)) { Close(); return false; } if(m_use_thread) Create(); m_open = true; return true; }
/** @brief getCurrentThread * get a handle on the thread this is called from * @return the handle of the thread this is called from */ ThreadHandle Threadler::getCurrentThread() { if (!isInit()) return ThreadHandle(); #ifdef WIN32 return GetCurrentThread(); #else return pthread_self(); #endif }
bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader, std::string device, bool passthrough, bool hw_decode, bool boost_on_downmix, bool use_thread, float queue_size, float fifo_size) { if(ThreadHandle()) Close(); if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_omx_reader = omx_reader; m_device = device; m_passthrough = false; m_hw_decode = false; m_use_passthrough = passthrough; m_use_hw_decode = hw_decode; m_boost_on_downmix = boost_on_downmix; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_use_thread = use_thread; m_flush = false; m_cached_size = 0; m_pAudioCodec = NULL; m_pChannelMap = NULL; if (queue_size != 0.0) m_max_data_size = queue_size * 1024 * 1024; if (fifo_size != 0.0) m_fifo_size = fifo_size; m_player_error = OpenAudioCodec(); if(!m_player_error) { Close(); return false; } m_player_error = OpenDecoder(); if(!m_player_error) { Close(); return false; } if(m_use_thread) Create(); m_open = true; return true; }
bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader, std::string device, bool passthrough, bool hw_decode, bool boost_on_downmix, bool use_thread) { if(ThreadHandle()) Close(); if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_omx_reader = omx_reader; m_device = device; m_passthrough = IAudioRenderer::ENCODED_NONE; m_hw_decode = false; m_use_passthrough = passthrough; m_use_hw_decode = hw_decode; m_boost_on_downmix = boost_on_downmix; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_use_thread = use_thread; m_flush = false; m_cached_size = 0; m_pAudioCodec = NULL; m_pChannelMap = NULL; m_speed = DVD_PLAYSPEED_NORMAL; // m_av_clock->SetMasterClock(false); m_player_error = OpenAudioCodec(); if(!m_player_error) { Close(); return false; } m_player_error = OpenDecoder(); if(!m_player_error) { Close(); return false; } if(m_use_thread) Create(); m_open = true; return true; }
bool OMXAudioPlayer::open(StreamInfo& hints, OMXClock *av_clock, OMXReader *omx_reader, std::string device) { if(ThreadHandle()) { close(); } if (!av_clock) { return false; } omxStreamInfo = hints; omxClock = av_clock; omxReader = omx_reader; deviceName = device; currentPTS = DVD_NOPTS_VALUE; doAbort = false; doFlush = false; cachedSize = 0; audioCodecOMX = NULL; channelMap = NULL; speed = DVD_PLAYSPEED_NORMAL; // omxClock->SetMasterClock(false); bool success = openCodec(); if(!success) { ofLogError(__func__) << "openCodec: " << success; close(); return success; } success = openDecoder(); if(!success) { ofLogError(__func__) << "openDecoder: " << success; close(); return success; } Create(); isOpen = true; return true; }
bool Thread::Start(WorkItem* work_item, void* data) { bool result = false; ThreadData* thread_data = new ThreadData; thread_data->item = work_item; thread_data->data = data; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 4096); result = pthread_create(ThreadHandle(), &attr, thread_func, thread_data) != 0; pthread_attr_destroy(&attr); return result; }
bool LimeMasterDownStream::Start(){ if(ThreadHandle()) Stop(); if(m_running) { FLog::Log(FLOG_DEBUG, "LimeMasterDownStream::Start - Message handler already running"); return false; } m_running = true; pthread_create(&m_thread, &m_tattr, &LimeMasterDownStream::Run, this); FLog::Log(FLOG_DEBUG, "LimeMasterDownStream::Start - Thread with id %d started", (int)m_thread); return true; }
bool OMXPlayerVideo::Open(COMXStreamInfo &hints, OMXClock *av_clock, const CRect& DestRect, EDEINTERLACEMODE deinterlace, bool hdmi_clock_sync, bool use_thread, float display_aspect, float queue_size, float fifo_size) { if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; if(ThreadHandle()) Close(); m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_fps = 25.0f; m_frametime = 0; m_Deinterlace = deinterlace; m_display_aspect = display_aspect; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_use_thread = use_thread; m_flush = false; m_cached_size = 0; m_iVideoDelay = 0; m_hdmi_clock_sync = hdmi_clock_sync; m_iSubtitleDelay = 0; m_pSubtitleCodec = NULL; m_DestRect = DestRect; if (queue_size != 0.0) m_max_data_size = queue_size * 1024 * 1024; if (fifo_size != 0.0) m_fifo_size = fifo_size; if(!OpenDecoder()) { Close(); return false; } if(m_use_thread) Create(); m_open = true; return true; }
bool OMXWrapper::Play() { if(ThreadHandle()) Stop(); if(m_running) { FLog::Log(FLOG_DEBUG, "OMXWrapper::Play - Video is already playing"); return false; } m_running = true; pthread_create(&m_thread, &m_tattr, &OMXWrapper::Run, this); FLog::Log(FLOG_DEBUG, "OMXWrapper::Play - Thread with id %d started", (int)m_thread); return true; }
bool OMXEGLImagePlayer::Open(COMXStreamInfo &hints, OMXClock *av_clock, EGLImageKHR eglImage_) { eglImage = eglImage_; ofLogVerbose() << "OMXEGLImagePlayer::maxDataSize may need to be reduced for 256 boards, memory intensive apps"; if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) { return false; } if(ThreadHandle()) { Close(); } m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_fps = 25.0f; m_frametime = 0; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_flush = false; m_cached_size = 0; m_iVideoDelay = 0; m_pts = 0; m_syncclock = true; m_speed = DVD_PLAYSPEED_NORMAL; m_FlipTimeStamp = m_av_clock->GetAbsoluteClock(); if(!OpenDecoder()) { Close(); return false; } Create(); m_open = true; return true; }
bool OMXPlayerAudio::Open(OMXClock *av_clock, const OMXAudioConfig &config, OMXReader *omx_reader) { if(ThreadHandle()) Close(); if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; m_dllAvFormat.av_register_all(); m_config = config; m_av_clock = av_clock; m_omx_reader = omx_reader; m_passthrough = false; m_hw_decode = false; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_flush = false; m_flush_requested = false; m_cached_size = 0; m_pAudioCodec = NULL; m_player_error = OpenAudioCodec(); if(!m_player_error) { Close(); return false; } m_player_error = OpenDecoder(); if(!m_player_error) { Close(); return false; } if(m_config.use_thread) Create(); m_open = true; return true; }
bool OMXPlayerVideo::Close() { m_bAbort = true; Flush(); if(ThreadHandle()) { Lock(); pthread_cond_broadcast(&m_packet_cond); UnLock(); StopThread(); } CloseDecoder(); m_open = false; m_stream_id = -1; m_iCurrentPts = DVD_NOPTS_VALUE; m_pStream = NULL; return true; }
bool CAMLPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) { try { CLog::Log(LOGNOTICE, "CAMLPlayer: Opening: %s", file.GetPath().c_str()); // if playing a file close it first // this has to be changed so we won't have to close it. if (ThreadHandle()) CloseFile(); m_item = file; m_options = options; m_elapsed_ms = 0; m_duration_ms = 0; m_audio_info = "none"; m_audio_delay = g_settings.m_currentVideoSettings.m_AudioDelay; m_video_info = "none"; m_video_width = 0; m_video_height = 0; m_video_fps_numerator = 25; m_video_fps_denominator = 1; m_subtitle_delay = 0; m_subtitle_thread = NULL; m_chapter_index = 0; m_chapter_count = 0; m_show_mainvideo = -1; m_dst_rect.SetRect(0, 0, 0, 0); ClearStreamInfos(); static URLProtocol vfs_protocol = { "vfs", CFileURLProtocol::Open, CFileURLProtocol::Read, CFileURLProtocol::Write, CFileURLProtocol::Seek, CFileURLProtocol::SeekEx, // url_exseek, an amlogic extension. CFileURLProtocol::Close, }; CStdString url = m_item.GetPath(); if (url.Left(strlen("smb://")).Equals("smb://")) { // the name string needs to persist static const char *smb_name = "smb"; vfs_protocol.name = smb_name; } else if (url.Left(strlen("afp://")).Equals("afp://")) { // the name string needs to persist static const char *afp_name = "afp"; vfs_protocol.name = afp_name; } else if (url.Left(strlen("nfs://")).Equals("nfs://")) { // the name string needs to persist static const char *nfs_name = "nfs"; vfs_protocol.name = nfs_name; } else if (url.Left(strlen("http://")).Equals("http://")) { // the name string needs to persist static const char *http_name = "xb-http"; vfs_protocol.name = http_name; url = "xb-" + url; } printf("CAMLPlayer::OpenFile: URL=%s\n", url.c_str()); if (player_init() != PLAYER_SUCCESS) { printf("player init failed\n"); return false; } printf("player init......\n"); // must be after player_init av_register_protocol2(&vfs_protocol, sizeof(vfs_protocol)); static play_control_t play_control; memset(&play_control, 0, sizeof(play_control_t)); // if we do not register a callback, // then the libamplayer will free run checking status. player_register_update_callback(&play_control.callback_fn, &UpdatePlayerInfo, 1000); // leak file_name for now. play_control.file_name = (char*)strdup(url.c_str()); //play_control->nosound = 1; // if disable audio...,must call this api play_control.video_index = -1; //MUST play_control.audio_index = -1; //MUST play_control.sub_index = -1; //MUST play_control.hassub = 1; play_control.t_pos = -1; play_control.need_start = 1; // if 0,you can omit player_start_play API. // just play video/audio immediately. // if 1,then need call "player_start_play" API; //play_control.auto_buffing_enable = 1; //play_control.buffing_min = 0.2; //play_control.buffing_middle = 0.5; //play_control.buffing_max = 0.8; //play_control.byteiobufsize =; // maps to av_open_input_file buffer size //play_control.loopbufsize =; //play_control.enable_rw_on_pause =; m_aml_state.clear(); m_aml_state.push_back(0); m_pid = player_start(&play_control, 0); if (m_pid < 0) { printf("player start failed! error = %d\n", m_pid); return false; } // setup to spin the busy dialog until we are playing m_ready.Reset(); g_renderManager.PreInit(); // create the playing thread m_StopPlaying = false; Create(); if (!m_ready.WaitMSec(100)) { CGUIDialogBusy *dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY); dialog->Show(); while (!m_ready.WaitMSec(1)) g_windowManager.ProcessRenderLoop(false); dialog->Close(); } // Playback might have been stopped due to some error. if (m_bStop || m_StopPlaying) return false; return true; } catch (...) { CLog::Log(LOGERROR, "%s - Exception thrown on open", __FUNCTION__); return false; } }
bool PAPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) { if (m_currentlyCrossFading) CloseFileInternal(false); //user seems to be in a hurry m_crossFading = g_guiSettings.GetInt("musicplayer.crossfade"); //WASAPI doesn't support multiple streams, no crossfading for cdda, cd-reading goes mad and no crossfading for last.fm doesn't like two connections if (file.IsCDDA() || file.IsLastFM() || g_guiSettings.GetString("audiooutput.audiodevice").find("wasapi:") != CStdString::npos) m_crossFading = 0; if (m_crossFading && IsPlaying()) { //do a short crossfade on trackskip //set to max 2 seconds for these prev/next transitions if (m_crossFading > 2) m_crossFading = 2; //queue for crossfading bool result = QueueNextFile(file, false); if (result) { //crossfading value may be update by QueueNextFile when nr of channels changed if (!m_crossFading) // swap to next track m_decoder[m_currentDecoder].SetStatus(STATUS_ENDED); else //force to fade to next track immediately m_forceFadeToNext = true; } return result; } // normal opening of file, nothing playing or crossfading not enabled // however no need to return to gui audio device CloseFileInternal(false); // always open the file using the current decoder m_currentDecoder = 0; if (!m_decoder[m_currentDecoder].Create(file, (__int64)(options.starttime * 1000), m_crossFading)) return false; m_iSpeed = 1; m_bPaused = false; m_bStopPlaying = false; m_bytesSentOut = 0; CLog::Log(LOGINFO, "PAPlayer: Playing %s", file.m_strPath.c_str()); m_timeOffset = (__int64)(options.starttime * 1000); unsigned int channel, sampleRate, bitsPerSample; m_decoder[m_currentDecoder].GetDataFormat(&channel, &sampleRate, &bitsPerSample); if (!CreateStream(m_currentStream, channel, sampleRate, bitsPerSample)) { m_decoder[m_currentDecoder].Destroy(); CLog::Log(LOGERROR, "PAPlayer::Unable to create audio stream"); } *m_currentFile = file; if (ThreadHandle() == NULL) Create(); m_startEvent.Set(); m_bIsPlaying = true; m_cachingNextFile = false; m_currentlyCrossFading = false; m_forceFadeToNext = false; m_bQueueFailed = false; m_decoder[m_currentDecoder].Start(); // start playback return true; }
bool MyRender::Play(OMXClock *av_clock, OMXPlayerVideo *m_player_video) { #else bool MyRender::Play() { #endif #ifndef RENDERTEST if (!av_clock) return false; #endif if(ThreadHandle()) Close(); #ifndef RENDERTEST m_av_clock = av_clock; vid = m_player_video; #endif if(m_running) { FLog::Log(FLOG_ERROR, "MyRender::%s - Thread already running\n", __func__); return false; } m_bStop = false; m_running = true; pthread_create(&m_thread, &m_tattr, &MyRender::Run, this); FLog::Log(FLOG_DEBUG, "MyRender::%s - Thread with id %d started\n", __func__, (int)m_thread); return true; } bool MyRender::Close() { if(!m_running) { FLog::Log(FLOG_DEBUG, "MyRender::%s - No thread running\n", __func__); return false; } if(renderer){ renderer->Stop(); } m_bStop = true; pthread_join(m_thread, NULL); m_running = false; m_thread = 0; FLog::Log(FLOG_DEBUG, "MyRender::%s - Thread stopped\n", __func__); return true; } bool MyRender::Running() { return m_running; } pthread_t MyRender::ThreadHandle() { return m_thread; } void *MyRender::Run(void *arg) { MyRender *thread = static_cast<MyRender *>(arg); thread->Process(); FLog::Log(FLOG_DEBUG, "MyRender::%s - Exited thread with id %d\n", __func__, (int)thread->ThreadHandle()); pthread_exit(NULL); }
/* * This loop is used to forward incoming Hti messages(arriving from CommChannelPlugin to m_QueueOut side) to correct SoapHandlers */ void HtiDispatcher::Run() { Util::Debug("HtiDispatcher::Run"); //m_testHandler.SetDispatcher(this); //m_testHandler.Start(); InitHandlers(); StartHandlers(); BYTE* shortData = NULL; //keep data if it's too short to have HtiHeader //or if one Data msg have more than one HtiMessage DWORD msgBufferSize = 8096; BYTE* msgBuffer = (BYTE*)malloc( msgBufferSize ); DWORD shortDataLen = 0; // By setting this threads priority below others will give soaphandler threads // more runtime to process the received messages.. This is to avoid the situation // where two messages arrive so close to each other that m_hReceiveHtiEvent is // signalled twice before the first message has even been processed by the soap plugin. if(!SetThreadPriority( ThreadHandle(), THREAD_PRIORITY_BELOW_NORMAL )) Util::Info("Warning: Could not set HtiDispatcher priority!"); while (m_Running) { try { Data* d = m_QueueOut->front(50); BYTE* p = (BYTE *)d->GetData(); DWORD l = d->GetLength(); //printf("\td = %d\n", m_QueueOut->size()); if (Util::GetVerboseLevel() == Util::VerboseLevel::debug) { char tmp[64]; sprintf(tmp, "[HtiDispatcher] HTI MsgSize = %d", l); string s(tmp); Util::Debug(s); //Util::Hex(p, d->GetLength()); } //Util::Debug("leftovers"); //copy leftovers to the beginning of the buffer if ( shortDataLen > 0 ) { memcpy( msgBuffer, shortData, shortDataLen ); } shortData = msgBuffer; //set shortData to the beginning //copy data to buffer if ( shortDataLen + l > msgBufferSize ) { msgBufferSize = shortDataLen + l; msgBuffer = (BYTE*)realloc(msgBuffer, msgBufferSize); shortData = msgBuffer; } //copy data gotten from queue to the end of shortData memcpy(shortData + shortDataLen, p, l ); shortDataLen = l + shortDataLen; while ( shortDataLen != 0 && (shortDataLen >= HtiMessage::MinHeaderSize() || m_IncomingHtiMessage != NULL ) ) { //new message if ( m_IncomingHtiMessage == NULL ) { if ( shortDataLen >= HtiMessage::MinHeaderSize() ) { if ( HtiMessage::CheckValidHtiHeader(shortData) ) { m_IncomingHtiMessage = new HtiMessage( shortData, shortDataLen ); if (Util::GetVerboseLevel() == Util::VerboseLevel::debug) { char tmp[64]; sprintf(tmp,"New hti message %d", m_IncomingHtiMessage->HtiDataSize()); string s(tmp); Util::Debug(s); //Util::Hex(p, d->GetLength()); } //_RPT2(_CRT_WARN, "income msg %x <%d>\n", m_IncomingHtiMessage, sizeof(HtiMessage)); //check message if ( m_IncomingHtiMessage->IsMessageComplete() ) { Util::Debug("HTI message complete"); DWORD msgSize = m_IncomingHtiMessage->HtiDataSize(); if ( msgSize < shortDataLen ) { //remove used part //BYTE* temp = new BYTE[shortDataLen-msgSize]; //_RPT2(_CRT_WARN, "temp %x <%d>\n", shortData , shortDataLen-msgSize); //memcpy(temp, shortData + msgSize, shortDataLen-msgSize); //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); //delete[] shortData; //shortData = temp; shortData += msgSize; //just move pointer shortDataLen -= msgSize; } else { //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); //delete[] shortData; //shortData = NULL; shortDataLen = 0; } //Dispatch incoming message DispatchToSoapHandlers(); } else { //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); //delete[] shortData; //shortData = NULL; shortDataLen = 0; } } else { //invalid header Util::Error("Invalid HTI header, dismiss Data message"); Util::Hex(shortData, HtiMessage::MinHeaderSize() ); //_RPT1(_CRT_WARN, "del shortData %x\n", shortData); //delete[] shortData; //shortData = NULL; shortDataLen = 0; } } } else //body parts { Util::Debug("add"); DWORD added = m_IncomingHtiMessage->AddToBody( shortData, shortDataLen ); //printf("reminder %d\n", m_IncomingHtiMessage->Reminder()); if ( added < shortDataLen ) { //only part of message was added //remove added part //BYTE* temp = new BYTE[shortDataLen-added]; //_RPT2(_CRT_WARN, "temp %x <%d>\n", shortData , shortDataLen-added); //memcpy(temp, shortData + added, shortDataLen-added); //_RPT1(_CRT_WARN, "del shortData %x\n", shortData ); //delete[] shortData; //shortData = temp; shortData += added; shortDataLen -= added; } else //all data were added { //_RPT1(_CRT_WARN, "del shortData %x\n", shortData ); //delete[] shortData; //shortData = NULL; shortDataLen = 0; } if ( m_IncomingHtiMessage->IsMessageComplete() ) { Util::Debug("HTI message complete"); //Dispatch incoming message DispatchToSoapHandlers(); } } } m_QueueOut->pop(); //_RPT1(_CRT_WARN, "del data %x\n", d); delete d; d = NULL; } catch (TimeoutException te) { //Util::Debug("[DataGatewaySocketWriterThread]timeout exception"); } } free( msgBuffer ); }
bool OMXPlayerAudio::Open(COMXStreamInfo &hints, OMXClock *av_clock, OMXReader *omx_reader, std::string device, bool passthrough, long initialVolume, bool hw_decode, bool boost_on_downmix, bool use_thread, float queue_size, float fifo_size) { if(ThreadHandle()) Close(); if (!m_dllAvUtil.Load() || !m_dllAvCodec.Load() || !m_dllAvFormat.Load() || !av_clock) return false; m_dllAvFormat.av_register_all(); m_hints = hints; m_av_clock = av_clock; m_omx_reader = omx_reader; m_device = device; m_passthrough = IAudioRenderer::ENCODED_NONE; m_hw_decode = false; m_use_passthrough = passthrough; m_use_hw_decode = hw_decode; m_boost_on_downmix = boost_on_downmix; m_iCurrentPts = DVD_NOPTS_VALUE; m_bAbort = false; m_bMpeg = m_omx_reader->IsMpegVideo(); m_use_thread = use_thread; m_flush = false; m_cached_size = 0; m_pAudioCodec = NULL; m_pChannelMap = NULL; m_speed = DVD_PLAYSPEED_NORMAL; m_initialVolume = initialVolume; if (queue_size != 0.0) m_max_data_size = queue_size * 1024 * 1024; if (fifo_size != 0.0) m_fifo_size = fifo_size; m_error = 0; m_errorbuff = 0; m_errorcount = 0; m_integral = 0; m_skipdupcount = 0; m_prevskipped = false; m_syncclock = true; m_errortime = m_av_clock->CurrentHostCounter(); m_freq = m_av_clock->CurrentHostFrequency(); m_av_clock->SetMasterClock(false); m_player_error = OpenAudioCodec(); if(!m_player_error) { Close(); return false; } m_player_error = OpenDecoder(); if(!m_player_error) { Close(); return false; } if(m_use_thread) Create(); m_open = true; return true; }
GlideComputer *glide_computer; ProtectedAirspaceWarningManager * GetAirspaceWarnings() { return glide_computer != nullptr ? &glide_computer->GetAirspaceWarnings() : nullptr; } #ifndef NDEBUG #ifdef ENABLE_OPENGL static const ThreadHandle zero_thread_handle = ThreadHandle(); static ThreadHandle draw_thread_handle; bool InDrawThread() { #ifdef ENABLE_OPENGL return InMainThread() && draw_thread_handle.IsInside(); #else return draw_thread != nullptr && draw_thread->IsInside(); #endif } void EnterDrawThread() {
template<class Acc, class Delta>typename QueuedMultiThreadAccumulator<Acc,Delta>::ThreadHandle QueuedMultiThreadAccumulator<Acc,Delta>::createThreadHandle() { return ThreadHandle(m_queueSize); }