bool SampleService::getFileInfos(
   BtpAction* action, DynamicObject& in, DynamicObject& out,
   DynamicObject& fileInfos)
{
   bool rval;

   // do not send dyno as response
   out.setNull();

   // get catalog interface
   CatalogInterface* ci = dynamic_cast<CatalogInterface*>(
      mNode->getModuleApiByType("bitmunk.catalog"));

   // get targeted node user
   DynamicObject vars;
   action->getResourceQuery(vars);
   if(!vars->hasMember("nodeuser"))
   {
      BM_ID_SET(vars["nodeuser"], mNode->getDefaultUserId());
   }

   // get resource parameters
   DynamicObject params;
   action->getResourceParams(params);

   // populate ware bundle
   Ware ware;
   BM_ID_SET(ware["mediaId"], BM_MEDIA_ID(params[0]));
   MediaPreferenceList mpl;
   mpl[0]["preferences"][0]["contentType"] = vars["contentType"];
   mpl[0]["preferences"][0]["minBitrate"] = 1;
   // FIXME: Make sure the node user is checked against logged in user?
   if((rval = ci->populateWareBundle(
      BM_USER_ID(vars["nodeuser"]), ware, mpl)))
   {
      FileInfoIterator i = ware["fileInfos"].getIterator();
      while(i->hasNext())
      {
         FileInfo& fi = i->next();

         // FIXME: get content type for file info instead of "extension"
         const char* extension = fi["extension"]->getString();
         // FIXME: only support for mp3 audio at this time
         if(strcmp(extension, "mp3") == 0)
         {
            // get sample range for file info
            Media media;
            BM_ID_SET(media["id"], BM_MEDIA_ID(fi["mediaId"]));
            if(getSampleRange(media))
            {
               fi["media"] = media;
               fileInfos->append() = fi;
            }
         }
      }
   }

   return rval;
}
Exemple #2
0
/**
 * Recursively applies context to the given input object.
 *
 * @param ctx the context to use.
 * @param usedCtx the used context values.
 * @param predicate the related predicate or NULL if none.
 * @param in the input object.
 * @param out the contextualized output object.
 */
static void _applyContext(
   DynamicObject& ctx, DynamicObject& usedCtx,
   const char* predicate, DynamicObject& in, DynamicObject& out)
{
   if(in.isNull())
   {
      out.setNull();
   }
   else
   {
      // initialize output
      DynamicObjectType inType = in->getType();
      out->setType(inType);

      if(inType == Map)
      {
         // add context to each property in the map
         char* tmp = NULL;
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            // compact predicate
            DynamicObject& next = i->next();
            DynamicObject cp(NULL);
            const char* p;
            if(strcmp(i->getName(), "@") == 0)
            {
               p = "@";
            }
            else
            {
               cp = _compactString(ctx, usedCtx, NULL, i->getName(), &tmp);
               p = cp;
            }
            // recurse
            _applyContext(ctx, usedCtx, p, next, out[p]);
         }
         free(tmp);
      }
      else if(inType == Array)
      {
         // apply context to each object in the array
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();
            _applyContext(ctx, usedCtx, predicate, next, out->append());
         }
      }
      // only strings need context applied, numbers & booleans don't
      else if(inType == String)
      {
         // compact string
         char* tmp = NULL;
         out = _compactString(ctx, usedCtx, predicate, in->getString(), &tmp);
         free(tmp);
      }
   }
}
Exemple #3
0
// Currently just handles top level and @:[...] constructs.
static bool _findId(DynamicObject& in, const char* id, DynamicObject& out)
{
   out.setNull();

   if(in->hasMember("@"))
   {
      DynamicObject& _id = in["@"];
      switch(_id->getType())
      {
         // top level object
         case String:
         {
            if(_id == id)
            {
               out = in;
            }
            break;
         }
         // top level is blank node
         case Array:
         {
            bool found = false;
            DynamicObjectIterator i = _id.getIterator();
            while(!found && i->hasNext())
            {
               DynamicObject& next = i->next();
               if(next["@"] == id)
               {
                  out = next;
                  found = true;
               }
            }
            break;
         }
         default:
            break;
      }
   }

   return true;
}
Exemple #4
0
/**
 * Recursively removes context from the given input object.
 *
 * @param ctx the context to use (changes during recursion as necessary).
 * @param in the input object.
 * @param out the normalized output object.
 * @param bnodeId the last blank node ID used.
 *
 * @return true on success, false on failure with exception set.
 */
static bool _removeContext(
   DynamicObject& ctx, DynamicObject& in, DynamicObject& out, int& bnodeId)
{
   bool rval = true;

   if(in.isNull())
   {
      out.setNull();
   }
   else
   {
      // initialize output
      DynamicObjectType inType = in->getType();
      out->setType(inType);

      // update context
      if(inType == Map && in->hasMember("#"))
      {
         ctx = in["#"];
      }

      if(inType == Map)
      {
         rval = _normalize(ctx, in, NULL, &out, bnodeId);
      }
      else if(inType == Array)
      {
         // strip context from each object in the array
         DynamicObjectIterator i = in.getIterator();
         while(i->hasNext())
         {
            DynamicObject& next = i->next();
            rval = _removeContext(ctx, next, out->append(), bnodeId);
         }
      }
   }

   return rval;
}
bool SampleService::getSampleFileByIds(
   BtpAction* action, DynamicObject& in, DynamicObject& out,
   MediaId mediaId, FileId fileId)
{
   bool rval;

   // do not send dyno as response
   out.setNull();

   // determine if too busy or not
   bool permit = false;
   mSampleSemaphoreLock.lock();
   {
      int current = mSampleSemaphore["current"]->getInt32();
      if(current < mSampleSemaphore["max"]->getInt32())
      {
         mSampleSemaphore["current"] = current + 1;
         permit = true;
      }
   }
   mSampleSemaphoreLock.unlock();

   // ensure permit was granted to stream sample
   if(!permit)
   {
      // too many samples streaming
      action->getResponse()->getHeader()->setStatus(503, "Service Unavailable");
      action->sendResult();
      rval = true;
   }
   else
   {
      // get catalog interface
      CatalogInterface* ci = dynamic_cast<CatalogInterface*>(
         mNode->getModuleApiByType("bitmunk.catalog"));

      // get targeted node user
      DynamicObject vars;
      action->getResourceQuery(vars);
      if(!vars->hasMember("nodeuser"))
      {
         BM_ID_SET(vars["nodeuser"], mNode->getDefaultUserId());
      }

      // get resource parameters
      DynamicObject params;
      action->getResourceParams(params);

      FileInfo fi;
      BM_ID_SET(fi["mediaId"], mediaId);
      BM_ID_SET(fi["id"], fileId);
      if((rval = ci->populateFileInfo(BM_USER_ID(vars["nodeuser"]), fi)))
      {
         // send the sample
         rval = sendFile(action, fi);
      }

      // release permit
      mSampleSemaphoreLock.lock();
      {
         int current = mSampleSemaphore["current"]->getInt32();
         mSampleSemaphore["current"] = current - 1;
      }
      mSampleSemaphoreLock.unlock();

      if(!rval)
      {
         // sample not found
         action->getResponse()->getHeader()->setStatus(404, "Not Found");
         action->sendResult();
         rval = true;
      }
   }

   return rval;
}