Beispiel #1
0
  static void Get(cDBusObject *Object, GVariant *Parameters, GDBusMethodInvocation *Invocation)
  {
    // only update recordings list if empty
    // so we don't mess around with the index values returned by List
    if (recordings.Count() == 0)
       recordings.Update(true);

    cRecording *recording = NULL;
    GVariant *first = g_variant_get_child_value(Parameters, 0);
    GVariant *refValue = first;
    if (g_variant_is_of_type(first, G_VARIANT_TYPE_VARIANT))
       refValue = g_variant_get_child_value(first, 0);
    if (g_variant_is_of_type(refValue, G_VARIANT_TYPE_STRING)) {
       const char *path = NULL;
       g_variant_get(refValue, "&s", &path);
       if ((path != NULL) && *path)
          recording = recordings.GetByName(path);
       }
    else if (g_variant_is_of_type(refValue, G_VARIANT_TYPE_INT32)) {
       int number = 0;
       g_variant_get(refValue, "i", &number);
       if ((number > 0) && (number <= recordings.Count()))
          recording = recordings.Get(number - 1);
       }
    if (refValue != first)
       g_variant_unref(refValue);
    g_variant_unref(first);

    GVariant *rec = BuildRecording(recording);
    g_dbus_method_invocation_return_value(Invocation, g_variant_new_tuple(&rec, 1));
  };
Beispiel #2
0
  static void List(cDBusObject *Object, GVariant *Parameters, GDBusMethodInvocation *Invocation)
  {
    recordings.Update(true);

    GVariantBuilder *array = g_variant_builder_new(G_VARIANT_TYPE("a(ia(sv))"));
    for (cRecording *r = recordings.First(); r; r = recordings.Next(r))
        g_variant_builder_add_value(array, BuildRecording(r));
    GVariant *a = g_variant_builder_end(array);
    g_dbus_method_invocation_return_value(Invocation, g_variant_new_tuple(&a, 1));
    g_variant_builder_unref(array);
  };
Beispiel #3
0
void RemoveDeletedRecordings(void)
{
  static time_t LastRemoveCheck = 0;
  if (time(NULL) - LastRemoveCheck > REMOVECHECKDELTA) {
     if (!RemoveDeletedRecordingsThread.Active()) {
        cThreadLock DeletedRecordingsLock(&DeletedRecordings);
        for (cRecording *r = DeletedRecordings.First(); r; r = DeletedRecordings.Next(r)) {
            if (r->deleted && time(NULL) - r->deleted > DELETEDLIFETIME) {
               RemoveDeletedRecordingsThread.Start();
               break;
               }
            }
        }
     LastRemoveCheck = time(NULL);
     }
}
void cRemoveDeletedRecordingsThread::Action(void)
{
  // Make sure only one instance of VDR does this:
  cLockFile LockFile(VideoDirectory);
  if (LockFile.Lock()) {
     bool deleted = false;
     cThreadLock DeletedRecordingsLock(&DeletedRecordings);
     for (cRecording *r = DeletedRecordings.First(); r; ) {
         if (r->deleted && time(NULL) - r->deleted > DELETEDLIFETIME) {
            cRecording *next = DeletedRecordings.Next(r);
            r->Remove();
            DeletedRecordings.Del(r);
            r = next;
            deleted = true;
            continue;
            }
         r = DeletedRecordings.Next(r);
         }
     if (deleted)
        RemoveEmptyVideoDirectories();
     }
}
Beispiel #5
0
void AssertFreeDiskSpace(int Priority, bool Force)
{
  static cMutex Mutex;
  cMutexLock MutexLock(&Mutex);
  // With every call to this function we try to actually remove
  // a file, or mark a file for removal ("delete" it), so that
  // it will get removed during the next call.
  static time_t LastFreeDiskCheck = 0;
  int Factor = (Priority == -1) ? 10 : 1;
  if (Force || time(NULL) - LastFreeDiskCheck > DISKCHECKDELTA / Factor) {
     if (!VideoFileSpaceAvailable(MINDISKSPACE)) {
        // Make sure only one instance of VDR does this:
        cLockFile LockFile(VideoDirectory);
        if (!LockFile.Lock())
           return;
        // Remove the oldest file that has been "deleted":
        isyslog("low disk space while recording, trying to remove a deleted recording...");
        cThreadLock DeletedRecordingsLock(&DeletedRecordings);
        if (DeletedRecordings.Count()) {
           cRecording *r = DeletedRecordings.First();
           cRecording *r0 = NULL;
           while (r) {
                 if (IsOnVideoDirectoryFileSystem(r->FileName())) { // only remove recordings that will actually increase the free video disk space
                    if (!r0 || r->start < r0->start)
                       r0 = r;
                    }
                 r = DeletedRecordings.Next(r);
                 }
           if (r0 && r0->Remove()) {
              DeletedRecordings.Del(r0);
              LastFreeDiskCheck += REMOVELATENCY / Factor;
              return;
              }
           }
        else {
           // DeletedRecordings was empty, so to be absolutely sure there are no
           // deleted recordings we need to double check:
           DeletedRecordings.Update(true);
           if (DeletedRecordings.Count())
              return; // the next call will actually remove it
           }
        // No "deleted" files to remove, so let's see if we can delete a recording:
        isyslog("...no deleted recording found, trying to delete an old recording...");
        cThreadLock RecordingsLock(&Recordings);
        if (Recordings.Count()) {
           cRecording *r = Recordings.First();
           cRecording *r0 = NULL;
           while (r) {
                 if (IsOnVideoDirectoryFileSystem(r->FileName())) { // only delete recordings that will actually increase the free video disk space
                    if (!r->IsEdited() && r->lifetime < MAXLIFETIME) { // edited recordings and recordings with MAXLIFETIME live forever
                       if ((r->lifetime == 0 && Priority > r->priority) || // the recording has no guaranteed lifetime and the new recording has higher priority
                           (r->lifetime > 0 && (time(NULL) - r->start) / SECSINDAY >= r->lifetime)) { // the recording's guaranteed lifetime has expired
                          if (r0) {
                             if (r->priority < r0->priority || (r->priority == r0->priority && r->start < r0->start))
                                r0 = r; // in any case we delete the one with the lowest priority (or the older one in case of equal priorities)
                             }
                          else
                             r0 = r;
                          }
                       }
                    }
                 r = Recordings.Next(r);
                 }
           if (r0 && r0->Delete()) {
              Recordings.Del(r0);
              return;
              }
           }
        // Unable to free disk space, but there's nothing we can do about that...
        isyslog("...no old recording found, giving up");
        Skins.QueueMessage(mtWarning, tr("Low disk space!"), 5, -1);
        }
     LastFreeDiskCheck = time(NULL);
     }
}
Beispiel #6
0
  static void Play(cDBusObject *Object, GVariant *Parameters, GDBusMethodInvocation *Invocation)
  {
    int replyCode = 501;
    cString replyMessage;
    cRecording *recording = NULL;
    int position = -1; // default: resume
    const char *hmsf = NULL;

    GVariant *first = g_variant_get_child_value(Parameters, 0);
    GVariant *refFirst = first;
    if (g_variant_is_of_type(first, G_VARIANT_TYPE_VARIANT))
       refFirst = g_variant_get_child_value(first, 0);
    GVariant *second = g_variant_get_child_value(Parameters, 1);
    GVariant *refSecond = first;
    if (g_variant_is_of_type(first, G_VARIANT_TYPE_VARIANT))
       refSecond = g_variant_get_child_value(first, 0);

    if (g_variant_is_of_type(refFirst, G_VARIANT_TYPE_STRING)) {
       const char *path = NULL;
       g_variant_get(refFirst, "&s", &path);
       if ((path != NULL) && *path) {
          recording = recordings.GetByName(path);
          if (recording == NULL) {
             recordings.Update(true);
             recording = recordings.GetByName(path);
             if (recording == NULL)
                replyMessage = cString::sprintf("recording \"%s\" not found", path);
             }
          }
       }
    else if (g_variant_is_of_type(refFirst, G_VARIANT_TYPE_INT32)) {
       int number = 0;
       g_variant_get(refFirst, "i", &number);
       if (number > 0) {
          recording = recordings.Get(number - 1);
          if (recording == NULL) {
             recordings.Update(true);
             recording = recordings.Get(number - 1);
             if (recording == NULL)
                replyMessage = cString::sprintf("recording \"%d\" not found", number);
             }
          }
       }

    if (recording != NULL) {
       if (g_variant_is_of_type(refSecond, G_VARIANT_TYPE_STRING)) {
          g_variant_get(refSecond, "&s", &hmsf);
          if ((hmsf != NULL) && *hmsf) {
             if (strcasecmp(hmsf, "begin") == 0) {
                position = 0;
                hmsf = NULL;
                }
             else
                position = HMSFToIndex(hmsf, recording->FramesPerSecond());
             }
          else
             hmsf = NULL;
          }
       else if (g_variant_is_of_type(refSecond, G_VARIANT_TYPE_INT32))
          g_variant_get(refSecond, "i", &position);

       replyCode = 250;
#if VDRVERSNUM < 10728
       cReplayControl::SetRecording(NULL, NULL);
#else
       cReplayControl::SetRecording(NULL);
#endif
       cControl::Shutdown();
       if (position >= 0) {
          cResumeFile resume(recording->FileName(), recording->IsPesRecording());
          if (position == 0)
             resume.Delete();
          else
             resume.Save(position);
          }
#if VDRVERSNUM < 10728
       cReplayControl::SetRecording(recording->FileName(), recording->Title());
#else
       cReplayControl::SetRecording(recording->FileName());
#endif
       cControl::Launch(new cReplayControl);
       cControl::Attach();

       if (hmsf != NULL)
          replyMessage = cString::sprintf("Playing recording \"%s\" from position %s", recording->FileName(), hmsf);
       else if (position >= 0)
          replyMessage = cString::sprintf("Playing recording \"%s\" from position %d", recording->FileName(), position);
       else
          replyMessage = cString::sprintf("Resume playing recording \"%s\"", recording->FileName());
       }
    cDBusHelper::SendReply(Invocation, replyCode, *replyMessage);
    if (refFirst != first)
       g_variant_unref(refFirst);
    g_variant_unref(first);
    if (refSecond != second)
       g_variant_unref(refSecond);
    g_variant_unref(second);
  };