Exemplo n.º 1
0
void cXVDRServer::Action(void)
{
  fd_set fds;
  struct timeval tv;
  cTimeMs channelReloadTimer;
  bool channelReloadTrigger = false;

  SetPriority(19);

  // get initial state of the recordings
  int recState = -1;
  Recordings.StateChanged(recState);

  // get initial state of the timers
  int timerState = -1;
  Timers.Modified(timerState);

  while (Running())
  {
    FD_ZERO(&fds);
    FD_SET(m_ServerFD, &fds);

    tv.tv_sec = 0;
    tv.tv_usec = 250*1000;

    int r = select(m_ServerFD + 1, &fds, NULL, NULL, &tv);
    if (r == -1)
    {
      ERRORLOG("failed during select");
      continue;
    }
    if (r == 0)
    {
      // remove disconnected clients
      for (ClientList::iterator i = m_clients.begin(); i != m_clients.end();)
      {
        if (!(*i)->Active())
        {
          INFOLOG("Client with ID %u seems to be disconnected, removing from client list", (*i)->GetID());
          delete (*i);
          i = m_clients.erase(i);
        }
        else {
          i++;
        }
      }

      // trigger clients to reload the modified channel list
      if(m_clients.size() > 0)
      {
        Channels.Lock(false);
        if(Channels.Modified() != 0)
        {
          channelReloadTrigger = true;
          channelReloadTimer.Set(0);
        }
        if(channelReloadTrigger && channelReloadTimer.Elapsed() >= 10*1000)
        {
          INFOLOG("Checking for channel updates ...");
          for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++)
            (*i)->ChannelChange();
          channelReloadTrigger = false;
          INFOLOG("Done.");
        }
        Channels.Unlock();
      }

      // reset inactivity timeout as long as there are clients connected
      if(m_clients.size() > 0) {
        ShutdownHandler.SetUserInactiveTimeout();
      }

      // update recordings
      if(Recordings.StateChanged(recState))
      {
        INFOLOG("Recordings state changed (%i)", recState);
        INFOLOG("Requesting clients to reload recordings list");
        for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++)
          (*i)->RecordingsChange();
      }

      // update timers
      if(Timers.Modified(timerState))
      {
        INFOLOG("Timers state changed (%i)", timerState);
        INFOLOG("Requesting clients to reload timers");
        for (ClientList::iterator i = m_clients.begin(); i != m_clients.end(); i++)
        {
         (*i)->TimerChange();
        }
      }
      continue;
    }

    int fd = accept(m_ServerFD, 0, 0);
    if (fd >= 0)
    {
      NewClientConnected(fd);
    }
    else
    {
      ERRORLOG("accept failed");
    }
  }
  return;
}
Exemplo n.º 2
0
void cHTSPData::Action()
{
  XBMC->Log(LOG_DEBUG, "%s - starting", __FUNCTION__);

  htsmsg_t* msg;
  if(!m_session.SendEnableAsync())
  {
    XBMC->Log(LOG_ERROR, "%s - couldn't send EnableAsync().", __FUNCTION__);
    m_started.Signal();
    return;
  }

  while (IsConnected() && Running())
  {
    if((msg = m_session.ReadMessage()) == NULL)
      break;

    uint32_t seq;
    if(htsmsg_get_u32(msg, "seq", &seq) == 0)
    {
      CMD_LOCK;
      SMessages::iterator it = m_queue.find(seq);
      if(it != m_queue.end())
      {
        it->second.msg = msg;
        it->second.event->Signal();
        continue;
      }
    }

    const char* method;
    if((method = htsmsg_get_str(msg, "method")) == NULL)
    {
      htsmsg_destroy(msg);
      continue;
    }

    CMD_LOCK;
    if     (strstr(method, "channelAdd"))
      cHTSPSession::ParseChannelUpdate(msg, m_channels);
    else if(strstr(method, "channelUpdate"))
      cHTSPSession::ParseChannelUpdate(msg, m_channels);
    else if(strstr(method, "channelDelete"))
      cHTSPSession::ParseChannelRemove(msg, m_channels);
    else if(strstr(method, "tagAdd"))
      cHTSPSession::ParseTagUpdate(msg, m_tags);
    else if(strstr(method, "tagUpdate"))
      cHTSPSession::ParseTagUpdate(msg, m_tags);
    else if(strstr(method, "tagDelete"))
      cHTSPSession::ParseTagRemove(msg, m_tags);
    else if(strstr(method, "initialSyncCompleted"))
      m_started.Signal();
    else if(strstr(method, "dvrEntryAdd"))
      cHTSPSession::ParseDVREntryUpdate(msg, m_recordings, g_bShowTimerNotifications && m_session.SendNotifications());
    else if(strstr(method, "dvrEntryUpdate"))
      cHTSPSession::ParseDVREntryUpdate(msg, m_recordings, g_bShowTimerNotifications && m_session.SendNotifications());
    else if(strstr(method, "dvrEntryDelete"))
      cHTSPSession::ParseDVREntryDelete(msg, m_recordings, g_bShowTimerNotifications && m_session.SendNotifications());
    else
      XBMC->Log(LOG_DEBUG, "%s - Unmapped action recieved '%s'", __FUNCTION__, method);

    htsmsg_destroy(msg);
  }

  m_started.Signal();
  XBMC->Log(LOG_DEBUG, "%s - exiting", __FUNCTION__);
}
Exemplo n.º 3
0
bool cRecorder::NextFile(void)
{
  if (recordFile && frameDetector->IndependentFrame()) { // every file shall start with an independent frame
#ifdef USE_HARDLINKCUTTER
     if (fileSize > fileName->MaxFileSize() || RunningLowOnDiskSpace()) {
#else
     if (fileSize > MEGABYTE(off_t(Setup.MaxVideoFileSize)) || RunningLowOnDiskSpace()) {
#endif /* HARDLINKCUTTER */
        recordFile = fileName->NextFile();
        fileSize = 0;
        }
     }
  return recordFile != NULL;
}

void cRecorder::Activate(bool On)
{
  if (On)
     Start();
  else
     Cancel(3);
}

void cRecorder::Receive(uchar *Data, int Length)
{
  if (Running()) {
     int p = ringBuffer->Put(Data, Length);
     if (p != Length && Running())
        ringBuffer->ReportOverflow(Length - p);
     }
}

void cRecorder::Action(void)
{
  time_t t = time(NULL);
  bool InfoWritten = false;
  bool FirstIframeSeen = false;
#ifdef USE_LIVEBUFFER
  double fps = DEFAULTFRAMESPERSECOND;
#endif /*USE_LIVEBUFFER*/
  while (Running()) {
        int r;
        uchar *b = ringBuffer->Get(r);
        if (b) {
           int Count = frameDetector->Analyze(b, r);
           if (Count) {
              if (!Running() && frameDetector->IndependentFrame()) // finish the recording before the next independent frame
                 break;
              if (frameDetector->Synced()) {
#ifdef USE_LIVEBUFFER
                 if(index && (frameDetector->FramesPerSecond() != fps)) {
                    fps = frameDetector->FramesPerSecond();
                    index->SetFramesPerSecond(fps);
                 } // if
#endif /*USE_LIVEBUFFER*/
                 if (!InfoWritten) {
                    cRecordingInfo RecordingInfo(recordingName);
                    if (RecordingInfo.Read()) {
                       if (frameDetector->FramesPerSecond() > 0 && DoubleEqual(RecordingInfo.FramesPerSecond(), DEFAULTFRAMESPERSECOND) && !DoubleEqual(RecordingInfo.FramesPerSecond(), frameDetector->FramesPerSecond())) {
                          RecordingInfo.SetFramesPerSecond(frameDetector->FramesPerSecond());
                          RecordingInfo.Write();
                          Recordings.UpdateByName(recordingName);
                          }
                       }
                    InfoWritten = true;
                    }
/*                 if (frameDetector->NewPayload()) { // We're at the first TS packet of a new payload...
                    if (Buffering)
                       esyslog("ERROR: encountered new payload while buffering - dropping some data!");
                    if (!frameDetector->NewFrame()) { // ...but the frame type is yet unknown, so we need to buffer packets until we see the frame type
                       if (!Buffer) {
                          dsyslog("frame type not in first packet of payload - buffering");
                          if (!(Buffer = MALLOC(uchar, BUFFERSIZE))) {
                             esyslog("ERROR: can't allocate frame type buffer");
                             break;
                             }
                          }
                       BufferIndex = 0;
                       Buffering = true;
                       }
                    }
                 else if (frameDetector->NewFrame()) // now we know the frame type, so stop buffering
                    Buffering = false;
                 if (Buffering) {
                    if (BufferIndex + Count <= BUFFERSIZE) {
                       memcpy(Buffer + BufferIndex, b, Count);
                       BufferIndex += Count;
                       }
                    else
                       esyslog("ERROR: too many bytes for frame type buffer (%d > %d) - dropped %d bytes", BufferIndex + Count, int(BUFFERSIZE), Count);
                    }
                 else if (FirstIframeSeen || frameDetector->IndependentFrame()) {
*/
#ifdef USE_LIVEBUFFER
                    if(!FirstIframeSeen) FillInitialData(b, r);
#endif /*USE_LIVEBUFFER*/
                 if (FirstIframeSeen || frameDetector->IndependentFrame()) {
                    FirstIframeSeen = true; // start recording with the first I-frame
                    if (!NextFile())
                       break;
                    if (index && frameDetector->NewFrame())
                       index->Write(frameDetector->IndependentFrame(), fileName->Number(), fileSize);
                    if (frameDetector->IndependentFrame()) {
                       recordFile->Write(patPmtGenerator.GetPat(), TS_SIZE);
                       fileSize += TS_SIZE;
                       int Index = 0;
                       while (uchar *pmt = patPmtGenerator.GetPmt(Index)) {
                             recordFile->Write(pmt, TS_SIZE);
                             fileSize += TS_SIZE;
                             }
                       }
                    if (recordFile->Write(b, Count) < 0) {
                       LOG_ERROR_STR(fileName->Name());
                       break;
                       }
                    fileSize += Count;
                    t = time(NULL);
                    }
                 }
              ringBuffer->Del(Count);
              }
           }
#ifdef USE_LIVEBUFFER
        if (handleError && (time(NULL) - t > MAXBROKENTIMEOUT)) {
#else
        if (time(NULL) - t > MAXBROKENTIMEOUT) {
#endif
#if REELVDR
           Skins.QueueMessage(mtError, tr("can't record - check your configuration"));
#else
           esyslog("ERROR: video data stream broken. Requesting Emergency Exit.");
           ShutdownHandler.RequestEmergencyExit();
#endif /*REELVDR*/
           t = time(NULL);
           }
        }
}
Exemplo n.º 4
0
void cPluginMcli::Action (void)
{
	netceiver_info_list_t *nc_list = nc_get_list ();
//	printf ("Looking for netceivers out there....\n");
	bool channel_switch_ok = false;

#define NOTIFY_CAM_CHANGE 1
#ifdef NOTIFY_CAM_CHANGE
    int cam_stats[CAM_POOL_MAX] = { 0 };
    char menu_strings[CAM_POOL_MAX][MAX_MENU_STR_LEN];
    bool first_run = true;

    for (int i = 0; i < CAM_POOL_MAX; i++)
        menu_strings[i][0] = '\0';
#endif
    /** lets inform vdr and its plugins if TunerChange event happened */
	bool netCVChanged;

	while (Running ()) {
		netCVChanged = false;
		Lock ();
		if(!InitMcli()) {
			usleep (250 * 1000);
			continue;
		}
		nc_lock_list ();
		time_t now = time (NULL);
		bool tpa = false;

		for (int n = 0; n < nc_list->nci_num; n++) {
			netceiver_info_t *nci = nc_list->nci + n;

			//printf("cPluginMcli::Action: NCI Cam_Num: %d\n", nci->cam_num);

			if ((now - nci->lastseen) > MCLI_DEVICE_TIMEOUT) {
				if(CAMPoolDel(nci->uuid)) {
					printf  ("Mcli::%s: Remove CAMs from NetCeiver: [%s]\n", __FUNCTION__, nci->uuid);
					netCVChanged = true;
				}
			} else {
				int cpa = CAMPoolAdd(nci);
				if(cpa==1) {
					printf ("Mcli::%s: Add CAMs from NetCeiver: [%s] -> %d\n", __FUNCTION__, nci->uuid, cpa);
					netCVChanged = true;
				}
			}

                        if (netCVChanged) {
				for(int j = 0; j < nci->cam_num; j++) {

					const char *camstate;
					const char *cammode;

					switch(nci->cam[j].status) {
						case DVBCA_CAMSTATE_MISSING: 
							camstate="MISSING"; break;
						case DVBCA_CAMSTATE_INITIALISING:
							camstate="INIT"; break;
						case DVBCA_CAMSTATE_READY:
							camstate="READY"; break;
					}
					switch(nci->cam[j].flags) {
						case CA_SINGLE:
							cammode="CA_SINGLE"; break;
						case CA_MULTI_SID:
							cammode="CA_MULTI_SID"; break;
						case CA_MULTI_TRANSPONDER:
							cammode="CA_MULTI_TRANSPONDER"; break;
					}

					if (nci->cam[j].status != DVBCA_CAMSTATE_MISSING) {
						printf("Mcli::%s: Slot:%d CamModule '%s' State:%s Mode:%s\n", __FUNCTION__, j, nci->cam[j].menu_string, camstate, cammode);
					} else {
						printf("Mcli::%s: Slot:%d CamModule State:%s\n", __FUNCTION__, j, camstate);
					}
				}
			}



#if NOTIFY_CAM_CHANGE
            if (n == 0) {
                for(int j = 0; j < nci->cam_num && j < CAM_POOL_MAX; j++) {
                    if (nci->cam[j].status != cam_stats[j]) {
                        char buf[64];
                        if (nci->cam[j].status) {
                            if(nci->cam[j].status == 2 && !first_run) {
                                snprintf(buf, 64, tr("Module '%s' ready"), nci->cam[j].menu_string);
                                Skins.QueueMessage(mtInfo, buf);
                            }
                            cam_stats[j] = nci->cam[j].status;
                            strncpy(menu_strings[j], nci->cam[j].menu_string, MAX_MENU_STR_LEN);
                        } else if (nci->cam[j].status == 0) {
                            cam_stats[j] = nci->cam[j].status;
                            if (!first_run) {
                                snprintf(buf, 64, tr("Module '%s' removed"), (char*)menu_strings[j]);
                                Skins.QueueMessage(mtInfo, buf);
                            }
                            menu_strings[j][0] = '\0';
                        }
                    }
                }
                first_run = false;
            }
#endif

			for (int i = 0; i < nci->tuner_num; i++) {
				tuner_pool_t *t = TunerFindByUUID (nci->tuner[i].uuid);
				if (((now - nci->lastseen) > MCLI_DEVICE_TIMEOUT) || (nci->tuner[i].preference < 0) || !strlen (nci->tuner[i].uuid)) {
					if (t) {
						int pos=TunerPoolDel(t);
						printf  ("Mcli::%s: Remove Tuner %s [%s] @ %d\n", __FUNCTION__, nci->tuner[i].fe_info.name, nci->tuner[i].uuid, pos);
						//isyslog ("cPluginMcli::Action: Remove Tuner %s [%s] @ %d", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, pos);
						netCVChanged = true;
					}
					continue;
				}
				if (!t) {
					tpa=TunerPoolAdd(nci->tuner+i);
					printf ("Mcli::%s: Add Tuner: %s [%s], Type %d @ %d\n", __FUNCTION__, nci->tuner[i].fe_info.name, nci->tuner[i].uuid, nci->tuner[i].fe_info.type, tpa);
					//isyslog ("cPluginMcli::Action: Add Tuner: %s [%s], Type %d @ %d", nci->tuner[i].fe_info.name, nci->tuner[i].uuid, nci->tuner[i].fe_info.type, tpa);
					netCVChanged = true;
				}
			}
		}
		nc_unlock_list ();
		Unlock ();
		UpdateDevices();

		if (netCVChanged) {
			//RC: disabled, see mantis #995
			//cPluginManager::CallAllServices("NetCeiver changed");
		}
        
//TB: reelvdr itself tunes if the first tuner appears, don't do it twice
#if 1 //ndef REELVDR
		if (tpa) {
			if (!channel_switch_ok) {	// the first tuner that was found, so make VDR retune to the channel it wants...
				cChannel *ch = Channels.GetByNumber (cDevice::CurrentChannel ());
				if (ch) {
					printf("Mcli::%s: cDevice::PrimaryDevice (%p)\n", __FUNCTION__, cDevice::PrimaryDevice ());
					channel_switch_ok = cDevice::PrimaryDevice ()->SwitchChannel (ch, true);
				}
			}
		} else {
			channel_switch_ok = 0;
		}
#endif

#ifdef TEMP_DISABLE_DEVICE
		TempDisableDevices();
#endif
		usleep (250 * 1000);
	}
}
Exemplo n.º 5
0
void cTrueColorDemo::Action(void)
{
  cPixmap *FadeInPixmap = NULL;
  cPixmap *FadeOutPixmap = NULL;
  cPixmap *MovePixmap = NULL;
  cPixmap *NextPixmap = NULL;
  cPixmap *TilePixmap = NULL;
  cPixmap *ScrollPixmap = NULL;
  cPixmap *AnimPixmap = NULL;
  cFont *OsdFont = cFont::CreateFont(Setup.FontOsd, Setup.FontOsdSize);
  cFont *SmlFont = cFont::CreateFont(Setup.FontSml, Setup.FontSmlSize);
  cFont *LrgFont = cFont::CreateFont(Setup.FontOsd, osd->Height() / 10);
  int FrameTime = 40; // ms
  int FadeTime = 1000; // ms
  int MoveTime = 4000; // ms
  int TileTime = 6000; // ms
  int ScrollWaitTime = 1000; // ms
  int ScrollLineTime = 200; // ms
  int ScrollTotalTime = 8000; // ms
  uint64_t Start = 0;
  uint64_t ScrollStartTime = 0;
  int ScrollLineNumber = 0;
  cPoint MoveStart, MoveEnd;
  cPoint TileStart, TileEnd;
  cPoint ScrollStart, ScrollEnd;
  int Line = osd->Height() / 20;
  int StartLine = Line;
  cPoint OldCursor;
  int State = 0;
  while (Running()) {
        cPixmap::Lock();
        bool Animated = false;
        uint64_t Now = cTimeMs::Now();
        if (FadeInPixmap) {
           double t = min(double(Now - Start) / FadeTime, 1.0);
           int Alpha = t * ALPHA_OPAQUE;
           FadeInPixmap->SetAlpha(Alpha);
           if (t >= 1)
              FadeInPixmap = NULL;
           Animated = true;
           }
        if (FadeOutPixmap) {
           double t = min(double(Now - Start) / FadeTime, 1.0);
           int Alpha = ALPHA_OPAQUE - t * ALPHA_OPAQUE;
           FadeOutPixmap->SetAlpha(Alpha);
           if (t >= 1)
              FadeOutPixmap = NULL;
           Animated = true;
           }
        if (MovePixmap) {
           double t = min(double(Now - Start) / MoveTime, 1.0);
           int x = MoveStart.X() + t * (MoveEnd.X() - MoveStart.X());
           int y = MoveStart.Y() + t * (MoveEnd.Y() - MoveStart.Y());
           cRect r = MovePixmap->ViewPort();
           r.SetPoint(x, y);
           MovePixmap->SetViewPort(r);
           if (t >= 1)
              MovePixmap = NULL;
           Animated = true;
           }
        if (TilePixmap) {
           double t = min(double(Now - Start) / TileTime, 1.0);
           int x = TileStart.X() + t * (TileEnd.X() - TileStart.X());
           int y = TileStart.Y() + t * (TileEnd.Y() - TileStart.Y());
           TilePixmap->SetDrawPortPoint(cPoint(x, y));
           if (t >= 1) {
              destroyablePixmap = TilePixmap;
              TilePixmap = NULL;
              }
           Animated = true;
           }
        if (ScrollPixmap) {
           if (int(Now - Start) > ScrollWaitTime) {
              if (ScrollStartTime) {
                 double t = min(double(Now - ScrollStartTime) / ScrollLineTime, 1.0);
                 int x = ScrollStart.X() + t * (ScrollEnd.X() - ScrollStart.X());
                 int y = ScrollStart.Y() + t * (ScrollEnd.Y() - ScrollStart.Y());
                 ScrollPixmap->SetDrawPortPoint(cPoint(x, y));
                 if (t >= 1) {
                    if (int(Now - Start) < ScrollTotalTime) {
                       cRect r = ScrollPixmap->DrawPort();
                       r.SetPoint(-r.X(), -r.Y());
                       ScrollPixmap->Pan(cPoint(0, 0), r);
                       cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
                       ScrollPixmap->DrawRectangle(cRect(0, ScrollPixmap->ViewPort().Height(), ScrollPixmap->DrawPort().Width(), ScrollPixmap->DrawPort().Height()), clrTransparent);
                       ScrollPixmap->DrawText(cPoint(0, ScrollPixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
                       ScrollStartTime = Now;
                       }
                    else {
                       FadeOutPixmap = ScrollPixmap;
                       ScrollPixmap = NULL;
                       Start = cTimeMs::Now();
                       }
                    }
                 }
              else
                 ScrollStartTime = Now;
              }
           Animated = true;
           }
        if (AnimPixmap) {
           int d = AnimPixmap->ViewPort().Height();
           if (clockwise)
              d = -d;
           cPoint p = AnimPixmap->DrawPort().Point().Shifted(0, d);
           if (clockwise && p.Y() <= -AnimPixmap->DrawPort().Height())
              p.SetY(0);
           else if (!clockwise && p.Y() > 0)
              p.SetY(-(AnimPixmap->DrawPort().Height() - AnimPixmap->ViewPort().Height()));
           AnimPixmap->SetDrawPortPoint(p);
           }
        if (!Animated) {
           switch (State) {
             case 0: {
                       FadeInPixmap = CreateTextPixmap("VDR", Line, 1, clrYellow, clrTransparent, LrgFont);
                       if (FadeInPixmap)
                          Line += FadeInPixmap->DrawPort().Height();
                       Start = cTimeMs::Now();
                       State++;
                     }
                     break;
             case 1: {
                       FadeInPixmap = CreateTextPixmap("Video Disk Recorder", Line, 3, clrYellow, clrTransparent, OsdFont);
                       if (FadeInPixmap)
                          Line += FadeInPixmap->DrawPort().Height();
                       Start = cTimeMs::Now();
                       State++;
                     }
                     break;
             case 2: {
                       FadeInPixmap = CreateTextPixmap("True Color OSD Demo", Line, 1, clrYellow, clrTransparent, OsdFont);
                       if (FadeInPixmap)
                          Line += FadeInPixmap->DrawPort().Height();
                       Start = cTimeMs::Now();
                       State++;
                     }
                     break;
             case 3: {
                       NextPixmap = CreateTextPixmap("Millions of colors", Line, 1, clrYellow, clrTransparent, LrgFont);
                       if (NextPixmap) {
                          FadeInPixmap = NextPixmap;
                          Start = cTimeMs::Now();
                          StartLine = Line;
                          Line += NextPixmap->DrawPort().Height();
                          }
                       State++;
                     }
                     break;
             case 4: {
                       Line += osd->Height() / 10;
                       int w = osd->Width() / 2;
                       int h = osd->Height() - Line - osd->Height() / 10;
                       cImage Image(cSize(w, h));
                       for (int y = 0; y < h; y++) {
                           for (int x = 0; x < w; x++)
                               Image.SetPixel(cPoint(x, y), HsvToColor(360 * double(x) / w, 1 - double(y) / h, 1) | 0xDF000000);
                           }
                       if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, Line, w, h))) {
                          Pixmap->DrawImage(cPoint(0, 0), Image);
                          toggleablePixmap = Pixmap;
                          }
                       State++;
                     }
                     break;
             case 5: {
                       if (NextPixmap) {
                          MovePixmap = NextPixmap;
                          MoveStart = MovePixmap->ViewPort().Point();
                          MoveEnd.Set(osd->Width() - MovePixmap->ViewPort().Width(), osd->Height() - MovePixmap->ViewPort().Height());
                          Start = cTimeMs::Now();
                          }
                       State++;
                     }
                     break;
             case 6: {
                       TilePixmap = CreateTextPixmap("Tiled Pixmaps", StartLine, 1, clrRed, clrWhite, OsdFont);
                       if (TilePixmap) {
                          TilePixmap->SetViewPort(TilePixmap->ViewPort().Grown(TilePixmap->DrawPort().Width(), TilePixmap->DrawPort().Height()));
                          TilePixmap->SetAlpha(200);
                          TilePixmap->SetTile(true);
                          TileStart = TilePixmap->DrawPort().Point();
                          TileEnd = TileStart.Shifted(TilePixmap->ViewPort().Width(), TilePixmap->ViewPort().Height());
                          MovePixmap = TilePixmap;
                          MoveStart = MovePixmap->ViewPort().Point();
                          MoveEnd.Set(10, osd->Height() - MovePixmap->ViewPort().Height() - 10);
                          Start = cTimeMs::Now();
                          }
                       State++;
                     }
                     break;
             case 7: {
                       const char *Text = "Scrolling Pixmaps";
                       int w = OsdFont->Width(Text);
                       int h = OsdFont->Height();
                       if (cPixmap *Pixmap = osd->CreatePixmap(2, cRect((osd->Width() - w) / 2, StartLine, w, 2 * h), cRect(0, 0, w, 3 * h))) {
                          Pixmap->Clear();
                          Pixmap->DrawText(cPoint(0, 0), Text, clrYellow, clrTransparent, OsdFont);
                          cString s = cString::sprintf("Line %d", ++ScrollLineNumber);
                          Pixmap->DrawText(cPoint(0, Pixmap->ViewPort().Height()), s, clrYellow, clrTransparent, OsdFont);
                          ScrollPixmap = Pixmap;
                          ScrollStart.Set(0, 0);
                          ScrollEnd.Set(0, -h);
                          Start = cTimeMs::Now();
                          }
                       State++;
                     }
                     break;
             case 8: {
                       const char *Text = "Animation";
                       const int Size = SmlFont->Width(Text) + 10;
                       const int NumDots = 12;
                       const int AnimFrames = NumDots;
                       // Temporarily using pixmap layer 0 to have the text alpha blended:
                       AnimPixmap = osd->CreatePixmap(0, cRect((osd->Width() - Size) / 2, StartLine, Size, Size), cRect(0, 0, Size, Size * AnimFrames));
                       if (AnimPixmap) {
                          AnimPixmap->SetAlpha(0);
                          AnimPixmap->Clear();
                          const int Diameter = Size / 5;
                          int xc = Size / 2 - Diameter / 2;
                          for (int Frame = 0; Frame < AnimFrames; Frame++) {
                              AnimPixmap->DrawEllipse(cRect(0, Frame * Size, Size, Size), 0xDDFFFFFF);
                              int yc = Frame * Size + Size / 2 - Diameter / 2;
                              int Color = 0xFF;
                              int Delta = Color / NumDots / 3;
                              for (int a = 0; a < NumDots; a++) {
                                  double t = 2 * M_PI * (Frame + a) / NumDots;
                                  int x = xc + ((Size - Diameter) / 2 - 5) * cos(t);
                                  int y = yc + ((Size - Diameter) / 2 - 5) * sin(t);
                                  AnimPixmap->DrawEllipse(cRect(x, y, Diameter, Diameter), ArgbToColor(0xFF, Color, Color, Color));
                                  Color -= Delta;
                                  }
                              AnimPixmap->DrawText(cPoint(0, Frame * Size), Text, clrBlack, clrTransparent, SmlFont, Size, Size, taCenter);
                              }
                          AnimPixmap->SetLayer(3); // now setting the actual pixmap layer
                          FadeInPixmap = AnimPixmap;
                          LOCK_THREAD;
                          OldCursor = cursor = AnimPixmap->ViewPort().Point();
                          cursorLimits.Set(0, 0, osd->Width(), osd->Height());
                          cursorLimits.SetRight(cursorLimits.Right() - Size);
                          cursorLimits.SetBottom(cursorLimits.Bottom() - Size);
                          cursorLimits.Grow(-10, -10);
                          Start = cTimeMs::Now();
                          }
                       State++;
                     }
                     break;
             case 9: {
                       LOCK_THREAD;
                       if (cursor != OldCursor) {
                          MovePixmap = AnimPixmap;
                          MoveStart = MovePixmap->ViewPort().Point();
                          MoveEnd = OldCursor = cursor;
                          MoveTime = 500;
                          Start = cTimeMs::Now();
                          }
                     }
                     break;
             }
           }
        osd->Flush();
        cPixmap::Unlock();
        int Delta = cTimeMs::Now() - Now;
        if (Delta < FrameTime)
           cCondWait::SleepMs(FrameTime - Delta);
        }
  destroyablePixmap = NULL;
  toggleablePixmap = NULL;
  delete OsdFont;
  delete SmlFont;
  delete LrgFont;
}
Exemplo n.º 6
0
void cVNSIStatus::Action(void)
{
  cTimeMs chanTimer(0);
  cTimeMs epgTimer(0);

  // get initial state of the recordings
#if VDRVERSNUM >= 20301
  cStateKey chanState;
  const cChannels *channels = cChannels::GetChannelsRead(chanState);
  chanState.Remove(false);
#endif

  // get initial state of the recordings
#if VDRVERSNUM >= 20301
  cStateKey recState;
  const cRecordings *recordings = cRecordings::GetRecordingsRead(recState);
  recState.Remove(false);
#else
  int recState = -1;
  Recordings.StateChanged(recState);
#endif

  // get initial state of the timers
#if VDRVERSNUM >= 20301
  cStateKey timerState;
  const cTimers *timers = cTimers::GetTimersRead(timerState);
  timerState.Remove(false);
#else
  int timerState = -1;
  Timers.Modified(timerState);
#endif

  // vnsitimer
  int vnsitimerState;
  m_vnsiTimers->StateChange(vnsitimerState);

  // last update of epg
#if VDRVERSNUM >= 20301
  cStateKey epgState;
  const cSchedules *epg = cSchedules::GetSchedulesRead(epgState);
  epgState.Remove(false);
#else
  time_t epgUpdate = cSchedules::Modified();
#endif

  // delete old timeshift file
  struct stat sb;
  if ((*TimeshiftBufferDir) && stat(TimeshiftBufferDir, &sb) == 0 && S_ISDIR(sb.st_mode))
  {
    DeleteFiles(TimeshiftBufferDir, ".vnsi");
  }
  else
  {
#if VDRVERSNUM >= 20102
    DeleteFiles(cVideoDirectory::Name(), ".vnsi");
#else
    DeleteFiles(VideoDirectory, ".vnsi");
#endif
  }

  // set thread priority
  SetPriority(1);

  while (Running())
  {
    m_mutex.Lock();

    // remove disconnected clients
    for (ClientList::iterator i = m_clients.begin(); i != m_clients.end();)
    {
      if (!i->Active())
      {
        INFOLOG("Client with ID %u seems to be disconnected, removing from client list", i->GetID());
        i = m_clients.erase(i);
      }
      else {
        i++;
      }
    }

    /*!
     * Don't to updates during running channel scan, KODI's PVR manager becomes
     * restarted of finished scan.
     */
    if (!cVNSIClient::InhibidDataUpdates())
    {
      // reset inactivity timeout as long as there are clients connected
      if (!m_clients.empty())
      {
        ShutdownHandler.SetUserInactiveTimeout();
      }

      // trigger clients to reload the modified channel list
      if(chanTimer.TimedOut())
      {
#if VDRVERSNUM >= 20301
        if (channels->Lock(chanState))
        {
          chanState.Remove(false);
          INFOLOG("Requesting clients to reload channel list");
          for (auto &i : m_clients)
            i.ChannelsChange();
          chanTimer.Set(5000);
        }
#else
        int modified = Channels.Modified();
        if (modified)
        {
          Channels.SetModified((modified == CHANNELSMOD_USER) ? true : false);
          INFOLOG("Requesting clients to reload channel list");
          for (auto &i : m_clients)
            i.ChannelsChange();
        }
        chanTimer.Set(5000);
#endif
      }


#if VDRVERSNUM >= 20301
      if (recordings->Lock(recState))
      {
        recState.Remove();
        INFOLOG("Requesting clients to reload recordings list");
        for (auto &i : m_clients)
        {
          i.RecordingsChange();
        }
      }

      if (timers->Lock(timerState))
      {
        timerState.Remove(false);
        INFOLOG("Requesting clients to reload timers");
        for (auto &i : m_clients)
        {
          i.SignalTimerChange();
        }
      }

      if (m_vnsiTimers->StateChange(vnsitimerState))
      {
        INFOLOG("Requesting clients to reload vnsi-timers");
        for (auto &i : m_clients)
        {
          i.SignalTimerChange();
        }
      }

      if (epgTimer.TimedOut())
      {
        if (epg->Lock(epgState))
        {
          epgState.Remove(false);
          DEBUGLOG("Requesting clients to load epg");
          int callAgain = 0;
          for (auto &i : m_clients)
          {
            callAgain |= i.EpgChange();
          }
          if (callAgain & VNSI_EPG_AGAIN)
          {
            epgTimer.Set(100);
            epgState.Reset();
          }
          else
          {
            if (callAgain & VNSI_EPG_PAUSE)
            {
              epgState.Reset();
            }
            epgTimer.Set(5000);
            m_vnsiTimers->Scan();
          }
        }
      }
#else
      // update recordings
      if(Recordings.StateChanged(recState))
      {
        INFOLOG("Recordings state changed (%i)", recState);
        INFOLOG("Requesting clients to reload recordings list");
        for (auto &i : m_clients)
          i.RecordingsChange();
      }

      // update timers
      if(Timers.Modified(timerState))
      {
        INFOLOG("Timers state changed (%i)", timerState);
        INFOLOG("Requesting clients to reload timers");
        for (auto &i : m_clients)
        {
          i.SignalTimerChange();
        }
      }

      // update epg
      if((cSchedules::Modified() > epgUpdate + 10) || time(NULL) > epgUpdate + 300)
      {
        for (auto &i : m_clients)
        {
          i.EpgChange();
        }
        epgUpdate = time(NULL);
      }
#endif
    }

    m_mutex.Unlock();

    usleep(250*1000);
  }
}
/*******************************************************************
*
* エレベーター制御文
*
*******************************************************************/
void Elevator::CntorolStatement()
{
	switch(m_ControlState)
	{
	case CONTROL::FREE://フリー状態
		break;

	case CONTROL::MOVE://目的フロア移動する状態
		//目的地でなければ
		if( !m_CDataSupport.isDestination() ){
			//エレベーター稼働
			Running();
		}
		//目的地ならば
		else{
			//エレベーター停止処理
			StopProcess();

			//全搭乗口の進路ガイドの方向を進路方向に変える
			setAllGuideVector(m_CDataSupport.m_CourseDirection);

			//制御を到着状態に
			m_ControlState = CONTROL::ARRIVE;
		}
		break;

	case CONTROL::ARRIVE://フロアに到着した状態
		//ゲートを開く
		if( m_CGate[m_Gate_Ypos]!=NULL ){
			//ゲートに開閉指示をだす
			m_CGate[m_Gate_Ypos]->StartOperation();
		}
		//制御を待機状態に
		m_ControlState = CONTROL::WAIT;
		break;

	case CONTROL::WAIT://待機状態
		//ゲートが完全に開いたら
		if( m_CGate[m_Gate_Ypos]->getDoorState() == ELEVATOR::OPEN ){
			//降りたい利用者を降ろす
			UserTakeDown();
			break;
		}
		//ゲートが半端なら
		else if( m_CGate[m_Gate_Ypos]->getDoorState() == ELEVATOR::HALF ){
			break;
		}
		//ゲートが完全に閉まっていれば
		else if( m_CGate[m_Gate_Ypos]->getDoorState() == ELEVATOR::CLOSE ){

			//待機時間をリセット
			m_CGate[m_Gate_Ypos]->OperationReset();

			//乗客がいれば
			if(m_isUserRiding){
				
				//同フロア対策
				m_State = m_CDataSupport.m_CourseDirection;

				//利用者の要求を追加
				addUserRequest();

				//始動準備させる
				StartSetting();
				break;
			}
			
			//要求が無ければ
			if( !m_CDataSupport.isCallRequest() )
			{
				DirectionClear();//エレベーターの方向データを全て初期化
				m_CGate[m_Gate_Ypos]->StateReset();//ゲートの状態を初期化
				m_ControlState = CONTROL::FREE;//制御をフリー状態に初期化
			}
		}
		break;
	}
}
Exemplo n.º 8
0
unsigned char cN2Timer::Ctrl(void)
{
  if(Running()) Update();
  return ctrl;
}
Exemplo n.º 9
0
void cConnection::Action(void)
{
  uint32_t kaTimeStamp;
  uint32_t channelID;
  uint32_t requestID;
  uint32_t opcode;
  uint32_t dataLength;
  uint8_t* data;

  while (Running())
  {
    if (!m_socket.read((uint8_t*)&channelID, sizeof(uint32_t))) break;
    channelID = ntohl(channelID);

    if (channelID == 1)
    {
      if (!m_socket.read((uint8_t*)&requestID, sizeof(uint32_t), 10000)) break;
      requestID = ntohl(requestID);

      if (!m_socket.read((uint8_t*)&opcode, sizeof(uint32_t), 10000)) break;
      opcode = ntohl(opcode);

      if (!m_socket.read((uint8_t*)&dataLength, sizeof(uint32_t), 10000)) break;
      dataLength = ntohl(dataLength);
      if (dataLength > 200000) // a random sanity limit
      {
        esyslog("VNSI-Error: dataLength > 200000!");
        break;
      }

      if (dataLength)
      {
        data = (uint8_t*)malloc(dataLength);
        if (!data)
        {
          esyslog("VNSI-Error: Extra data buffer malloc error");
          break;
        }

        if (!m_socket.read(data, dataLength, 10000))
        {
          esyslog("VNSI-Error: Could not read data");
          free(data);
          break;
        }
      }
      else
      {
        data = NULL;
      }

      //LOGCONSOLE("Received chan=%lu, ser=%lu, op=%lu, edl=%lu", channelID, requestID, opcode, dataLength);

      if (!m_loggedIn && (opcode != 1))
      {
        esyslog("VNSI-Error: Not logged in and opcode != 1");
        if (data) free(data);
        break;
      }

      /* Handle channel open and close inside this thread */
      if (opcode == VDR_CHANNELSTREAM_OPEN)
      {
        cResponsePacket *resp = new cResponsePacket();
        if (!resp->init(requestID))
        {
          esyslog("VNSI-Error: response packet init fail");
          delete resp;
          continue;
        }

        uint32_t number = ntohl(*(uint32_t*)&data[0]);
        free(data);

        if (m_isStreaming)
          StopChannelStreaming();

        const cChannel *channel = Channels.GetByNumber(number);
        if (channel != NULL)
        {
          if (StartChannelStreaming(channel, resp))
          {
            isyslog("VNSI: Started streaming of channel %i - %s", number, channel->Name());
            continue;
          }
          else
          {
            LOGCONSOLE("Can't stream channel %i - %s", number, channel->Name());
            resp->add_U32(VDR_RET_DATALOCKED);
          }
        }
        else
        {
          esyslog("VNSI-Error: Can't find channel %i", number);
          resp->add_U32(VDR_RET_DATAINVALID);
        }

        resp->finalise();
        m_socket.write(resp->getPtr(), resp->getLen());
      }
      else if (opcode == VDR_CHANNELSTREAM_CLOSE)
      {
        if (m_isStreaming)
          StopChannelStreaming();
      }
      else
      {
        cRequestPacket* req = new cRequestPacket(requestID, opcode, data, dataLength, this);
        m_cmdcontrol.recvRequest(req);
      }
    }
    else if (channelID == 3)
    {
      if (!m_socket.read((uint8_t*)&kaTimeStamp, sizeof(uint32_t), 1000)) break;
      kaTimeStamp = ntohl(kaTimeStamp);

      uint8_t buffer[8];
      *(uint32_t*)&buffer[0] = htonl(3); // KA CHANNEL
      *(uint32_t*)&buffer[4] = htonl(kaTimeStamp);
      if (!m_socket.write(buffer, 8))
      {
        esyslog("VNSI-Error: Could not send back KA reply");
        break;
      }
    }
    else
    {
      esyslog("VNSI-Error: Incoming channel number unknown");
      break;
    }
  }

  /* If thread is ended due to closed connection delete a
     possible running stream here */
  StopChannelStreaming();
}
Exemplo n.º 10
0
unsigned int cN2Timer::Cycles(void)
{
  if(Running()) Update();
  PRINTF(L_SYS_EMU,"n2timer %d: read %u %02x %02x = %02x",nr,cycles,ctrl&0xff,latch&0xff,val);
  return val;
}
Exemplo n.º 11
0
void cAction::Action(void)
{
  if(pri>0) SetPriority(pri);
  struct pollfd *pfd=0;
  while(Running()) {
    if(filters.Count()<=0) {
      cCondWait::SleepMs(100);
      }
    else {
      // first build pfd data
      Lock();
      delete[] pfd; pfd=new struct pollfd[filters.Count()];
      if(!pfd) {
        PRINTF(L_GEN_ERROR,"action %s: pollfd: out of memory",id);
        break;
        }
      int num=0;
      cPidFilter *filter;
      for(filter=filters.First(); filter; filter=filters.Next(filter))
        if(filter->Active()) {
          memset(&pfd[num],0,sizeof(struct pollfd));
          pfd[num].fd=filter->fd;
          pfd[num].events=POLLIN;
          num++;
          }
      Unlock();

      // now poll for data
      int r=poll(pfd,num,60);
      if(r<0 && errno!=EINTR) {
        PRINTF(L_GEN_ERROR,"action %s poll: %s",id,strerror(errno));
        break;
        }
      if(r>0) {
        for(r=0 ; r<num ; r++)
          if(pfd[r].revents&POLLIN) {
            Lock();
            for(filter=filters.First(); filter; filter=filters.Next(filter)) {
              if(filter->fd==pfd[r].fd) {
                unsigned char buff[MAX_SECT_SIZE];
                int n=read(filter->fd,buff,sizeof(buff));
                if(n<0 && errno!=EAGAIN) {
                  if(errno==EOVERFLOW) {
                    filter->Flush();
                    //PRINTF(L_GEN_ERROR,"action %s read: Buffer overflow",filter->id);
                    }
                  else PRINTF(L_GEN_ERROR,"action %s read: %s",filter->id,strerror(errno));
                  }
                if(n>0) {
                  filter->lastTime.Set(); filter->forceRun=false;
                  Process(filter,buff,n);
                  // don't make any assumption about data-structs here
                  // Process() may have changed them
                  }
                break;
                }
              }
            Unlock();
            }
        }

      // call filters which are idle too long
      Lock();
      do {
        r=0;
        for(filter=filters.First(); filter; filter=filters.Next(filter)) {
          if(filter->forceRun || (filter->idleTime && filter->lastTime.Elapsed()>filter->idleTime)) {
            filter->lastTime.Set(); filter->forceRun=false;
            Process(filter,0,0);
            // don't make any assumption about data-structs here
            // Process() may have changed them
            r=1; break;
            }
          }
        } while(r);
      Unlock();
      }
    }
  delete[] pfd;
}
Exemplo n.º 12
0
void cLiveStreamer::Action(void)
{
  int size = 0;
  unsigned char *buf = NULL;
  m_startup = true;

  while (Running())
  {
    size = 0;
    buf = Get(size);

    {
      cMutexLock lock(&m_FilterMutex);
      if (!IsAttached())
      {
        INFOLOG("returning from streamer thread, receiver is no more attached");
        Clear();
        sendDetach();
        return;
      }
    }

    if(!IsStarting() && (m_last_tick.Elapsed() > (uint64_t)(m_scanTimeout*1000)) && !m_SignalLost)
    {
      INFOLOG("timeout. signal lost!");
      sendStatus(XVDR_STREAM_STATUS_SIGNALLOST);
      m_SignalLost = true;
    }

    // no data
    if (buf == NULL || size <= TS_SIZE)
      continue;

    // Sync to TS packet
    int used = 0;
    while (size > TS_SIZE)
    {
      if (buf[0] == TS_SYNC_BYTE && buf[TS_SIZE] == TS_SYNC_BYTE)
        break;
      used++;
      buf++;
      size--;
    }
    Del(used);


    while (size >= TS_SIZE)
    {
      if(!Running())
        break;

      // TS packet sync not found !
      if (buf[0] != TS_SYNC_BYTE)
        break;

      unsigned int ts_pid = TsPid(buf);

      {
        cMutexLock lock(&m_FilterMutex);
        cTSDemuxer *demuxer = FindStreamDemuxer(ts_pid);

        if (demuxer)
          demuxer->ProcessTSPacket(buf);
      }

      buf += TS_SIZE;
      size -= TS_SIZE;
      Del(TS_SIZE);
    }
  }
}
void cRawWriter::Action(void)
{
  uint64_t NextHeaderPos = 0ULL;
  uint64_t GetPos        = 0ULL;
  cPoller  Poller(m_fd, true);

  while (Running()) {

    if (!Poller.Poll(100))
      continue;

    uint64_t StartPos;
    int      Count = 0;
    int      n;
    uchar   *Data = m_RingBuffer.Get(Count);

    if (!Data || Count <= 0)
      continue;

    Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32)
    StartPos = m_DiscardEnd;
    Unlock();

    // Next frame ?
    if (NextHeaderPos == GetPos) {

      // Discard data ?
      if (StartPos > GetPos) {
        // we're at frame boundary
        Count = min(Count, (int)(StartPos - GetPos));

        m_RingBuffer.Del(Count);
        GetPos += Count;
        NextHeaderPos = GetPos;
        continue;
      }

      // Next frame

      if (Count < 6)
        LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !");

      int packlen = DATA_IS_TS(Data) ? TS_SIZE : pes_packet_len(Data, Count);

      if (Count < packlen)
        ;//LOGMSG("Count = %d < %d", Count,
      //   header->len + sizeof(stream_tcp_header_t));
      else
        Count = packlen;
      NextHeaderPos = GetPos + packlen;

    } else {
      // end of prev frame
      Count = min(Count, (int)(NextHeaderPos-GetPos));
    }

    errno = 0;
    n = write(m_fd, Data, Count);

    if (n <= 0) {
      if (n == 0) {
        LOGERR("cBackgroundWriter: Client disconnected data stream ?");
        break;
      }

      if (errno == EINTR || errno == EWOULDBLOCK)
        continue;

      LOGERR("cBackgroundWriter: TCP write error");
      break;
    }

    GetPos += n;
    m_RingBuffer.Del(n);
  }

  m_RingBuffer.Clear();
}
void cTcpWriter::Action(void)
{
  uint64_t NextHeaderPos = 0;
  uint64_t GetPos        = 0;
  cPoller  Poller (m_fd, true);
  bool     CorkReq = false;

  while (Running()) {

    if (!Poller.Poll(100))
      continue;

    if (CorkReq && m_RingBuffer.Available() <= 0) {
      // Force TCP packet to avoid delaying control messages
      Cork();
      CorkReq = false;
    }

    uint64_t StartPos;
    int      Count = 0;
    int      n;
    uchar   *Data = m_RingBuffer.Get(Count);

    if (!Data || Count <= 0)
      continue;

    Lock(); // uint64_t m_DiscardStart can not be read atomically (IA32)
    StartPos = m_DiscardEnd;
    Unlock();

    // Next frame ?
    if (NextHeaderPos == GetPos) {

      // Discard data ?
      if (StartPos > GetPos) {
        // we're at frame boundary
        // drop only data packets, not control messages
        stream_tcp_header_t *header = (stream_tcp_header_t*)Data;
        if (eStreamId(header->stream) == sidVdr) {
          Count = min(Count, (int)(StartPos - GetPos));

          // size of next (complete) packet.
          // drop only one packet at time.
          int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t);
          if (Count >= pkt_len) {
            // drop only complete packets.
            // some packets are not dropped (packets overlapping end of ringbuffer)
            Count = pkt_len;

            m_RingBuffer.Del(Count);
            GetPos += Count;
            NextHeaderPos = GetPos;

            CorkReq = true; // force sending last frame

            continue;
          }
        }
      }

      // Next frame

      if (Count < (int)sizeof(stream_tcp_header_t))
        LOGMSG("cBackgroundWriter @NextHeaderPos: Count < header size !");

      // limit single write to size of next (complete) packet.
      // (we need to track packet boundaries)
      stream_tcp_header_t *header = (stream_tcp_header_t*)Data;
      int pkt_len = ntohl(header->len) + sizeof(stream_tcp_header_t);
      if (Count > pkt_len)
        Count = pkt_len;
      // next packet start position in stream
      NextHeaderPos = GetPos + pkt_len;

      // check for control message
      if (eStreamId(header->stream) == sidControl)
        CorkReq = true;

    } else {
      // end of prev frame
      Count = min(Count, (int)(NextHeaderPos-GetPos));
    }

    errno = 0;
    n = write(m_fd, Data, Count);

    if (n <= 0) {

      if (n == 0) {
        LOGERR("cBackgroundWriter: Client disconnected data stream ?");
        break;
      }

      if (errno == EINTR || errno == EWOULDBLOCK)
        continue;

      LOGERR("cBackgroundWriter: TCP write error");
      break;
    }

    GetPos += n;
    m_RingBuffer.Del(n);
  }

  m_RingBuffer.Clear();
}