use of org.opencastproject.mediapackage.MediaPackageElement in project opencast by opencast.
the class SchedulerRestService method startCapture.
@POST
@Path("capture/{agent}")
@RestQuery(name = "startcapture", description = "Create an immediate event", returnDescription = "If events were successfully generated, status CREATED is returned", pathParameters = { @RestParameter(name = "agent", isRequired = true, type = Type.STRING, description = "The agent identifier") }, restParameters = { @RestParameter(name = "workflowDefinitionId", isRequired = false, type = Type.STRING, description = "The workflow definition id to use") }, reponses = { @RestResponse(responseCode = HttpServletResponse.SC_CREATED, description = "Recording started"), @RestResponse(responseCode = HttpServletResponse.SC_NOT_FOUND, description = "There is no such agent"), @RestResponse(responseCode = HttpServletResponse.SC_CONFLICT, description = "The agent is already recording"), @RestResponse(responseCode = HttpServletResponse.SC_UNAUTHORIZED, description = "You do not have permission to start this immediate capture. Maybe you need to authenticate."), @RestResponse(responseCode = HttpServletResponse.SC_SERVICE_UNAVAILABLE, description = "The agent is not ready to communicate") })
public Response startCapture(@PathParam("agent") String agentId, @FormParam("workflowDefinitionId") String wfId) throws NotFoundException, UnauthorizedException {
if (service == null || agentService == null || prolongingService == null)
return Response.serverError().status(Response.Status.SERVICE_UNAVAILABLE).entity("Scheduler service is unavailable, please wait...").build();
// Lookup the agent. If it doesn't exist, add a temporary registration
boolean adHocRegistration = false;
try {
agentService.getAgent(agentId);
} catch (NotFoundException e) {
Properties adHocProperties = new Properties();
adHocProperties.put(AGENT_REGISTRATION_TYPE, AGENT_REGISTRATION_TYPE_ADHOC);
agentService.setAgentConfiguration(agentId, adHocProperties);
agentService.setAgentState(agentId, AgentState.CAPTURING);
adHocRegistration = true;
logger.info("Temporarily registered agent '{}' for ad-hoc recording", agentId);
}
try {
Date now = new Date();
Date temporaryEndDate = DateTime.now().plus(prolongingService.getInitialTime()).toDate();
try {
List<MediaPackage> events = service.findConflictingEvents(agentId, now, temporaryEndDate);
if (!events.isEmpty()) {
logger.info("An already existing event is in a conflict with the the one to be created on the agent {}!", agentId);
return Response.status(Status.CONFLICT).build();
}
} catch (SchedulerException e) {
logger.error("Unable to create immediate event on agent {}: {}", agentId, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
String workflowId = defaultWorkflowDefinitionId;
if (StringUtils.isNotBlank(wfId))
workflowId = wfId;
Map<String, String> caProperties = new HashMap<>();
caProperties.put("org.opencastproject.workflow.definition", workflowId);
caProperties.put("event.location", agentId);
caProperties.put("event.title", "Capture now event");
// caProperties.put("org.opencastproject.workflow.config.captionHold", "false");
// caProperties.put("org.opencastproject.workflow.config.archiveOp", "true");
// caProperties.put("org.opencastproject.workflow.config.trimHold", "false");
// TODO default metadata? configurable?
// A temporal with start and end period is needed! As well PROPERTY_SPATIAL is needed
DublinCoreCatalog eventCatalog = DublinCores.mkOpencastEpisode().getCatalog();
eventCatalog.set(PROPERTY_TITLE, "Capture now event");
eventCatalog.set(PROPERTY_TEMPORAL, EncodingSchemeUtils.encodePeriod(new DCMIPeriod(now, temporaryEndDate), Precision.Second));
eventCatalog.set(PROPERTY_SPATIAL, agentId);
eventCatalog.set(PROPERTY_CREATED, EncodingSchemeUtils.encodeDate(new Date(), Precision.Minute));
// eventCatalog.set(PROPERTY_CREATOR, "demo");
// eventCatalog.set(PROPERTY_SUBJECT, "demo");
// eventCatalog.set(PROPERTY_LANGUAGE, "demo");
// eventCatalog.set(PROPERTY_CONTRIBUTOR, "demo");
// eventCatalog.set(PROPERTY_DESCRIPTION, "demo");
// TODO workflow properties
Map<String, String> wfProperties = new HashMap<>();
MediaPackage mediaPackage = null;
try {
mediaPackage = MediaPackageBuilderFactory.newInstance().newMediaPackageBuilder().createNew();
mediaPackage = addCatalog(workspace, IOUtils.toInputStream(eventCatalog.toXmlString(), "UTF-8"), "dublincore.xml", MediaPackageElements.EPISODE, mediaPackage);
prolongingService.schedule(agentId);
service.addEvent(now, temporaryEndDate, agentId, Collections.<String>emptySet(), mediaPackage, wfProperties, caProperties, Opt.<Boolean>none(), Opt.<String>none(), SchedulerService.ORIGIN);
return Response.status(Status.CREATED).header("Location", serverUrl + serviceUrl + '/' + mediaPackage.getIdentifier().compact() + ".xml").build();
} catch (Exception e) {
prolongingService.stop(agentId);
if (e instanceof UnauthorizedException)
throw (UnauthorizedException) e;
logger.error("Unable to create immediate event on agent {}: {}", agentId, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} finally {
if (mediaPackage != null) {
for (MediaPackageElement elem : $(mediaPackage.getElements()).bind(MediaPackageSupport.Filters.byFlavor(MediaPackageElements.EPISODE).toFn())) {
try {
workspace.delete(elem.getURI());
} catch (NotFoundException e) {
logger.warn("Unable to find (and hence, delete), this mediapackage '{}' element '{}'", mediaPackage.getIdentifier(), elem.getIdentifier());
} catch (IOException e) {
chuck(e);
}
}
}
}
} catch (Throwable t) {
throw t;
} finally {
if (adHocRegistration) {
agentService.removeAgent(agentId);
logger.info("Removed temporary registration for agent '{}'", agentId);
}
}
}
use of org.opencastproject.mediapackage.MediaPackageElement in project opencast by opencast.
the class AbstractFeedGenerator method getEnclosures.
/**
* Returns the identifier of those tracks that are to be included as enclosures in the feed. Note that for a feed type
* of {@link Feed.Type#RSS}, the list must exactly contain one single entry.
* <p>
* This default implementation will include the track identified by the flavor as specified in the constructor for rss
* feeds and every distribution track for atom feeds.
*
* @param feed
* the feed
* @param resultItem
* the result item
* @return the set of identifier
*/
protected List<MediaPackageElement> getEnclosures(Feed feed, SearchResultItem resultItem) {
MediaPackage mediaPackage = resultItem.getMediaPackage();
List<MediaPackageElement> candidateElements = new ArrayList<MediaPackageElement>();
List<MediaPackageElementFlavor> flavors = new ArrayList<MediaPackageElementFlavor>();
Set<String> tags = new HashSet<String>();
switch(feed.getType()) {
case Atom:
flavors.addAll(atomTrackFlavors);
tags.addAll(atomTags);
break;
default:
flavors.addAll(rssTrackFlavors);
tags.addAll(rssTags);
break;
}
// Collect track id's by flavor
if (flavors.size() > 0) {
for (MediaPackageElementFlavor flavor : flavors) {
MediaPackageElement[] elements = mediaPackage.getElementsByFlavor(flavor);
for (MediaPackageElement element : elements) {
if (element.containsTag(tags)) {
candidateElements.add(element);
}
}
}
}
if (candidateElements.size() == 0) {
logger.debug("No distributed media found for feed entry '{}'", resultItem.getDcTitle());
}
return candidateElements;
}
use of org.opencastproject.mediapackage.MediaPackageElement in project opencast by opencast.
the class AbstractFeedGenerator method addEpisode.
/**
* Adds episode information to the feed.
*
* @param feed
* the feed
* @param query
* the query that results in the feed
* @param resultItem
* the episodes item
* @param organization
* the organization
* @return the feed
*/
protected Feed addEpisode(Feed feed, String[] query, SearchResultItem resultItem, Organization organization) {
String link = getLinkForEntry(feed, resultItem, organization);
String title = resultItem.getDcTitle();
// Get the media enclosures
List<MediaPackageElement> enclosures = getEnclosures(feed, resultItem);
if (enclosures.size() == 0) {
logger.debug("No media formats found for feed entry: {}", title);
return feed;
}
String entryUri = null;
// For RSS feeds, create multiple entries (one per enclosure). For Atom, add all enclosures to the same item
switch(feed.getType()) {
case RSS:
entryUri = resultItem.getId();
for (MediaPackageElement e : enclosures) {
List<MediaPackageElement> enclosure = new ArrayList<MediaPackageElement>(1);
enclosure.add(e);
FeedEntry entry = createEntry(feed, title, link, entryUri);
entry = populateFeedEntry(entry, resultItem, enclosure);
entry.setUri(entry.getUri() + "/" + e.getIdentifier());
feed.addEntry(entry);
}
break;
case Atom:
entryUri = generateEntryUri(resultItem.getId());
FeedEntry entry = createEntry(feed, title, link, entryUri);
entry = populateFeedEntry(entry, resultItem, enclosures);
if (getLinkSelf(organization) != null) {
LinkImpl self = new LinkImpl(getSelfLinkForEntry(feed, resultItem, organization));
self.setRel("self");
entry.addLink(self);
}
feed.addEntry(entry);
if (feed.getUpdatedDate() == null)
feed.setUpdatedDate(entry.getUpdatedDate());
else if (entry.getUpdatedDate().before(feed.getUpdatedDate()))
feed.setUpdatedDate(entry.getUpdatedDate());
break;
default:
throw new IllegalStateException("Unsupported feed type " + feed.getType());
}
return feed;
}
use of org.opencastproject.mediapackage.MediaPackageElement in project opencast by opencast.
the class AbstractFeedGenerator method populateFeedEntry.
/**
* Populates the feed entry with metadata and the enclosures.
*
* @param entry
* the entry to enrich
* @param metadata
* the metadata
* @param enclosures
* the media enclosures
* @return the enriched item
*/
private FeedEntry populateFeedEntry(FeedEntry entry, SearchResultItem metadata, List<MediaPackageElement> enclosures) {
Date d = metadata.getDcCreated();
Date updatedDate = metadata.getModified();
String title = metadata.getDcTitle();
// Configure the iTunes extension
ITunesFeedEntryExtension iTunesEntry = new ITunesFeedEntryExtension();
iTunesEntry.setDuration(metadata.getDcExtent());
iTunesEntry.setBlocked(false);
iTunesEntry.setExplicit(false);
if (StringUtils.isNotBlank(metadata.getDcCreator()))
iTunesEntry.setAuthor(metadata.getDcCreator());
// TODO: Add iTunes keywords and subtitles
// iTunesEntry.setKeywords(keywords);
// iTunesEntry.setSubtitle(subtitle);
// Configure the DC extension
DublinCoreExtension dcExtension = new DublinCoreExtension();
dcExtension.setTitle(title);
dcExtension.setIdentifier(metadata.getId());
// Set contributor
if (!StringUtils.isEmpty(metadata.getDcContributor())) {
for (String contributor : metadata.getDcContributor().split(";;")) {
entry.addContributor(new PersonImpl(contributor));
dcExtension.addContributor(contributor);
}
}
// Set creator
if (!StringUtils.isEmpty(metadata.getDcCreator())) {
for (String creator : metadata.getDcCreator().split(";;")) {
if (iTunesEntry.getAuthor() == null)
iTunesEntry.setAuthor(creator);
entry.addAuthor(new PersonImpl(creator));
dcExtension.addCreator(creator);
}
}
// Set publisher
if (!StringUtils.isEmpty(metadata.getDcPublisher())) {
dcExtension.addPublisher(metadata.getDcPublisher());
}
// Set rights
if (!StringUtils.isEmpty(metadata.getDcAccessRights())) {
dcExtension.setRights(metadata.getDcAccessRights());
}
// Set description
if (!StringUtils.isEmpty(metadata.getDcDescription())) {
String summary = metadata.getDcDescription();
entry.setDescription(new ContentImpl(summary));
iTunesEntry.setSummary(summary);
dcExtension.setDescription(summary);
}
// Set the language
if (!StringUtils.isEmpty(metadata.getDcLanguage())) {
dcExtension.setLanguage(metadata.getDcLanguage());
}
// Set the publication date
if (d != null) {
entry.setPublishedDate(d);
dcExtension.setDate(d);
} else if (metadata.getModified() != null) {
entry.setPublishedDate(metadata.getModified());
dcExtension.setDate(metadata.getModified());
}
// Set the updated date
if (updatedDate == null)
updatedDate = d;
entry.setUpdatedDate(updatedDate);
// TODO: Finish dc support
// Set format
// if (!StringUtils.isEmpty(resultItem.getMediaType())) {
// dcExtension.setFormat(resultItem.getMediaType());
// }
// dcEntry.setCoverage(arg0);
// dcEntry.setRelation(arg0);
// dcEntry.setSource(arg0);
// dcEntry.setSubject(arg0);
// Set the cover image
String coverUrl = null;
if (!StringUtils.isEmpty(metadata.getCover())) {
coverUrl = metadata.getCover();
setImage(entry, coverUrl);
}
entry.addExtension(iTunesEntry);
entry.addExtension(dcExtension);
// Add the enclosures
for (MediaPackageElement element : enclosures) {
String trackMimeType = element.getMimeType().toString();
long trackLength = element.getSize();
if (trackLength <= 0 && element instanceof Track) {
// filesize unset so estimate from duration and bitrate
trackLength = 0;
if (((TrackImpl) element).hasVideo()) {
List<VideoStream> video = ((TrackImpl) element).getVideo();
if (video.get(0).getBitRate() != null) {
trackLength += metadata.getDcExtent() / 1000 * video.get(0).getBitRate() / 8;
}
}
if (((TrackImpl) element).hasAudio()) {
List<AudioStream> audio = ((TrackImpl) element).getAudio();
if (audio.get(0).getBitRate() != null) {
trackLength += metadata.getDcExtent() / 1000 * audio.get(0).getBitRate() / 8;
}
}
}
// order of magnitude correct
if (trackLength <= 0) {
trackLength = metadata.getDcExtent();
}
String trackFlavor = element.getFlavor().toString();
String trackUrl = null;
try {
trackUrl = element.getURI().toURL().toExternalForm();
} catch (MalformedURLException e) {
// Can't happen
}
Enclosure enclosure = new EnclosureImpl(trackUrl, trackMimeType, trackFlavor, trackLength);
entry.addEnclosure(enclosure);
}
return entry;
}
use of org.opencastproject.mediapackage.MediaPackageElement in project opencast by opencast.
the class OaiPmhPublicationServiceImpl method retract.
protected Publication retract(Job job, MediaPackage mediaPackage, String repository) throws PublicationException, NotFoundException {
String mpId = mediaPackage.getIdentifier().compact();
// track elements for retraction
MediaPackage oaiPmhMp = null;
SearchResult searchResult = oaiPmhDatabase.search(QueryBuilder.queryRepo(repository).mediaPackageId(mpId).isDeleted(false).build());
for (SearchResultItem searchResultItem : searchResult.getItems()) {
if (oaiPmhMp == null) {
oaiPmhMp = searchResultItem.getMediaPackage();
} else {
for (MediaPackageElement mpe : searchResultItem.getMediaPackage().getElements()) {
oaiPmhMp.add(mpe);
}
}
}
// retract oai-pmh
try {
oaiPmhDatabase.delete(mpId, repository);
} catch (OaiPmhDatabaseException e) {
throw new PublicationException(format("Unable to retract media package %s from OAI-PMH repository %s", mpId, repository), e);
}
if (oaiPmhMp != null && oaiPmhMp.getElements().length > 0) {
// retract files from distribution channels
Set<String> mpeIds = new HashSet<>();
for (MediaPackageElement mpe : oaiPmhMp.elements()) {
if (MediaPackageElement.Type.Publication == mpe.getElementType())
continue;
mpeIds.add(mpe.getIdentifier());
}
if (!mpeIds.isEmpty()) {
List<Job> retractionJobs = new ArrayList<>();
// retract download
try {
Job retractDownloadJob = downloadDistributionService.retract(getPublicationChannelName(repository), oaiPmhMp, mpeIds);
if (retractDownloadJob != null) {
retractionJobs.add(retractDownloadJob);
}
} catch (DistributionException e) {
throw new PublicationException(format("Unable to create retraction job from distribution channel download for the media package %s ", mpId), e);
}
// retract streaming
try {
Job retractDownloadJob = streamingDistributionService.retract(getPublicationChannelName(repository), oaiPmhMp, mpeIds);
if (retractDownloadJob != null) {
retractionJobs.add(retractDownloadJob);
}
} catch (DistributionException e) {
throw new PublicationException(format("Unable to create retraction job from distribution channel streaming for the media package %s ", mpId), e);
}
if (retractionJobs.size() > 0) {
// wait for distribution jobs
if (!waitForJobs(job, serviceRegistry, retractionJobs).isSuccess())
throw new PublicationException(format("Unable to retract elements of media package %s from distribution channels.", mpId));
}
}
}
String publicationChannel = getPublicationChannelName(repository);
for (Publication p : mediaPackage.getPublications()) {
if (StringUtils.equals(publicationChannel, p.getChannel()))
return p;
}
return null;
}
Aggregations