/* * JAME 6.2.1 * http://jame.sourceforge.net * * Copyright 2001, 2016 Andrea Medeghini * * This file is part of JAME. * * JAME is an application for creating fractals and other graphics artifacts. * * JAME is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * JAME is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with JAME. If not, see <http://www.gnu.org/licenses/>. * */ package net.sf.jame.queue; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import net.sf.jame.core.extension.Extension; import net.sf.jame.core.util.ProgressListener; import net.sf.jame.core.xml.XML; import net.sf.jame.core.xml.XMLNodeBuilder; import net.sf.jame.queue.clip.RenderClipDataRow; import net.sf.jame.queue.clip.RenderClipService; import net.sf.jame.queue.encoder.EncoderContext; import net.sf.jame.queue.encoder.EncoderException; import net.sf.jame.queue.encoder.RAFEncoderContext; import net.sf.jame.queue.encoder.extension.EncoderExtensionRuntime; import net.sf.jame.queue.io.ChunkedRandomAccessFile; import net.sf.jame.queue.job.RenderJob; import net.sf.jame.queue.job.RenderJobDataRow; import net.sf.jame.queue.job.RenderJobService; import net.sf.jame.queue.profile.RenderProfileDataRow; import net.sf.jame.queue.profile.RenderProfileService; import net.sf.jame.queue.spool.JobData; import net.sf.jame.twister.TwisterClip; import net.sf.jame.twister.TwisterClipController; import net.sf.jame.twister.TwisterClipXMLExporter; import net.sf.jame.twister.TwisterClipXMLImporter; import net.sf.jame.twister.TwisterConfig; import net.sf.jame.twister.TwisterRegistry; import net.sf.jame.twister.TwisterSequence; import net.sf.jame.twister.converter.extension.ConverterExtensionRuntime; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * @author Andrea Medeghini */ public class LibraryService { private static final Logger logger = Logger.getLogger(LibraryService.class.getName()); public static final int TILE_WIDTH = 256; public static final int TILE_HEIGHT = 256; private final List<LibraryServiceListener> listeners = new ArrayList<LibraryServiceListener>(); private RenderProfileService profileService; private RenderJobService jobService; private RenderClipService clipService; private final File workdir; private Session session; /** * @param session * @param workdir * @throws RenderServiceException */ public LibraryService(final Session session, final File workdir) throws RenderServiceException { try { clipService = new RenderClipService(workdir); profileService = new RenderProfileService(workdir); jobService = new RenderJobService(workdir); this.workdir = workdir; this.session = session; clipService.init(session); profileService.init(session); jobService.init(session); } catch (final Exception e) { throw new RenderServiceException(e); } } /** * @return * @throws RenderServiceException */ public List<RenderClipDataRow> loadClips() throws RenderServiceException { try { session.openTransaction(); final List<RenderClipDataRow> clips = clipService.loadAll(session); session.closeTransaction(); for (RenderClipDataRow clip : clips) { fireClipLoaded(clip); } return clips; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clip * @param clip * @throws RenderServiceException */ public void createClip(final RenderClipDataRow clip, final TwisterClip twisterClip) throws RenderServiceException { try { session.openTransaction(); clipService.create(session, clip); session.closeTransaction(); if (twisterClip != null) { final TwisterClipXMLExporter exporter = new TwisterClipXMLExporter(); final Document doc = XML.createDocument(); final XMLNodeBuilder builder = XML.createDefaultXMLNodeBuilder(doc); final Element element = exporter.exportToElement(twisterClip, builder); doc.appendChild(element); final OutputStream os = getClipOutputStream(clip.getClipId()); XML.saveDocument(os, "twister-clip.xml", doc); os.close(); } fireClipCreated(clip); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clip * @throws RenderServiceException */ public void saveClip(final RenderClipDataRow clip) throws RenderServiceException { try { session.openTransaction(); clipService.save(session, clip); session.closeTransaction(); fireClipUpdated(clip); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clip * @throws RenderServiceException */ public void deleteClip(final RenderClipDataRow clip) throws RenderServiceException { try { session.openTransaction(); final List<RenderProfileDataRow> profiles = profileService.loadAll(session, clip.getClipId()); for (final RenderProfileDataRow profile : profiles) { profileService.delete(session, profile); } clipService.delete(session, clip); session.closeTransaction(); for (final RenderProfileDataRow profile : profiles) { fireProfileDeleted(profile); } fireClipDeleted(clip); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clipId * @return * @throws RenderServiceException */ public RenderClipDataRow getClip(final int clipId) throws RenderServiceException { try { session.openTransaction(); final RenderClipDataRow clip = clipService.getClip(session, clipId); session.closeTransaction(); return clip; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clipId * @return * @throws RenderServiceException */ public List<RenderProfileDataRow> loadProfiles(final int clipId) throws RenderServiceException { try { session.openTransaction(); final List<RenderProfileDataRow> profiles = profileService.loadAll(session, clipId); session.closeTransaction(); for (RenderProfileDataRow profile : profiles) { fireProfileLoaded(profile); } return profiles; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param clipId * @return */ public List<RenderProfileDataRow> resetProfiles(final int clipId) throws RenderServiceException { try { session.openTransaction(); final List<RenderProfileDataRow> profiles = profileService.loadAll(session, clipId); for (final RenderProfileDataRow profile : profiles) { profile.setJobCreated(0); profile.setJobStored(0); profileService.saveJobs(session, profile); profileService.clean(session, profile); } session.closeTransaction(); for (final RenderProfileDataRow profile : profiles) { fireProfileUpdated(profile); } return profiles; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profile * @throws RenderServiceException */ public void createProfile(final RenderProfileDataRow profile) throws RenderServiceException { try { session.openTransaction(); profileService.create(session, profile); session.closeTransaction(); fireProfileCreated(profile); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profile * @throws RenderServiceException */ public void saveProfile(final RenderProfileDataRow profile) throws RenderServiceException { try { session.openTransaction(); profileService.save(session, profile); session.closeTransaction(); fireProfileUpdated(profile); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profile * @throws RenderServiceException */ public void deleteProfile(final RenderProfileDataRow profile) throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session, profile.getProfileId()); for (final RenderJobDataRow job : jobs) { jobService.delete(session, job); } profileService.delete(session, profile); session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobDeleted(job); } fireProfileDeleted(profile); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @return * @throws RenderServiceException */ public RenderProfileDataRow getProfile(final int profileId) throws RenderServiceException { try { session.openTransaction(); final RenderProfileDataRow profile = profileService.getProfile(session, profileId); session.closeTransaction(); return profile; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } // /** // * @param profileId // * @return // * @throws ServiceException // */ // public List<RenderJobDataRow> loadJobs(final int profileId) throws ServiceException { // try { // session.openTransaction(); // final List<RenderJobDataRow> jobs = jobService.loadAll(session, profileId); // session.closeTransaction(); // return jobs; // } // catch (final TransactionException e) { // throw new ServiceException(e); // } // catch (final Exception e) { // try { // session.abortTransaction(); // } // catch (final TransactionException x) { // x.printStackTrace(); // } // throw new ServiceException(e); // } // } /** * @return * @throws RenderServiceException */ public List<RenderJobDataRow> loadJobs() throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session); session.closeTransaction(); return jobs; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void createJob(final RenderJobDataRow job) throws RenderServiceException { try { session.openTransaction(); final RenderProfileDataRow profile = profileService.getProfile(session, job.getProfileId()); final RenderClipDataRow clip = clipService.getClip(session, profile.getClipId()); clip.setStatus(clip.getStatus() + 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() + 1); profileService.saveStatus(session, profile); jobService.create(session, job); startJob(job); session.closeTransaction(); fireProfileUpdated(profile); fireClipUpdated(clip); fireJobCreated(job); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void saveJob(final RenderJobDataRow job) throws RenderServiceException { try { session.openTransaction(); jobService.save(session, job); session.closeTransaction(); fireJobUpdated(job); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void deleteJob(final RenderJobDataRow job) throws RenderServiceException { try { session.openTransaction(); final RenderProfileDataRow profile = profileService.getProfile(session, job.getProfileId()); final RenderClipDataRow clip = clipService.getClip(session, profile.getClipId()); clip.setStatus(clip.getStatus() - 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() - 1); profileService.saveStatus(session, profile); stopJob(job); jobService.delete(session, job); session.closeTransaction(); fireProfileUpdated(profile); fireClipUpdated(clip); fireJobAborted(job); fireJobStopped(job); fireJobDeleted(job); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param jobId * @return * @throws RenderServiceException */ public RenderJobDataRow getJob(final int jobId) throws RenderServiceException { try { session.openTransaction(); final RenderJobDataRow job = jobService.getJob(session, jobId); session.closeTransaction(); return job; } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void saveJobStatus(final RenderJobDataRow job) throws RenderServiceException { try { session.openTransaction(); jobService.saveStatus(session, job); session.closeTransaction(); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } private void startJob(final RenderJobDataRow job) throws RenderServiceException { try { job.setStatus(1); jobService.saveStatus(session, job); } catch (final Exception e) { throw new RenderServiceException(e); } } private void stopJob(final RenderJobDataRow job) throws RenderServiceException { try { job.setStatus(0); jobService.saveStatus(session, job); } catch (final Exception e) { throw new RenderServiceException(e); } } /** * @throws RenderServiceException */ public void startJobs() throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session); for (final RenderJobDataRow job : jobs) { startJob(job); } session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobStarted(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @throws RenderServiceException */ public void stopJobs() throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session); for (final RenderJobDataRow job : jobs) { stopJob(job); } session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobAborted(job); } for (final RenderJobDataRow job : jobs) { fireJobStopped(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @throws RenderServiceException */ public void deleteJobs() throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session); for (final RenderJobDataRow job : jobs) { stopJob(job); jobService.delete(session, job); } final List<RenderProfileDataRow> profiles = profileService.loadAll(session); for (final RenderProfileDataRow profile : profiles) { profile.setStatus(0); profileService.saveStatus(session, profile); } final List<RenderClipDataRow> clips = clipService.loadAll(session); for (final RenderClipDataRow clip : clips) { clip.setStatus(0); clipService.saveStatus(session, clip); } session.closeTransaction(); for (final RenderProfileDataRow profile : profiles) { fireProfileUpdated(profile); } for (final RenderClipDataRow clip : clips) { fireClipUpdated(clip); } for (final RenderJobDataRow job : jobs) { fireJobAborted(job); } for (final RenderJobDataRow job : jobs) { fireJobStopped(job); } for (final RenderJobDataRow job : jobs) { fireJobDeleted(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @param listener * @param message * @param percentage * @throws RenderServiceException */ public void startJobs(final int profileId, final ProgressListener listener, final String message, final float percentage) throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session, profileId); for (int i = 0; i < jobs.size(); i++) { RenderJobDataRow job = jobs.get(i); listener.stateChanged(message, (int) Math.rint((((float) i) / (jobs.size() - 1)) * 100f)); startJob(job); } session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobStarted(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @param listener * @param message * @param percentage * @throws RenderServiceException */ public void stopJobs(final int profileId, final ProgressListener listener, final String message, final float percentage) throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session, profileId); for (int i = 0; i < jobs.size(); i++) { RenderJobDataRow job = jobs.get(i); listener.stateChanged(message, (int) Math.rint((((float) i) / (jobs.size() - 1)) * 100f)); stopJob(job); } session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobAborted(job); } for (final RenderJobDataRow job : jobs) { fireJobStopped(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @throws RenderServiceException */ public void resumeJobs() throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session); session.closeTransaction(); for (final RenderJobDataRow job : jobs) { fireJobResumed(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @param listener * @param percentage * @throws RenderServiceException */ public void deleteJobs(final int profileId, final ProgressListener listener, final String message, final float percentage) throws RenderServiceException { try { session.openTransaction(); final List<RenderJobDataRow> jobs = jobService.loadAll(session, profileId); final RenderProfileDataRow profile = profileService.getProfile(session, profileId); final RenderClipDataRow clip = clipService.getClip(session, profile.getClipId()); for (int i = 0; i < jobs.size(); i++) { RenderJobDataRow job = jobs.get(i); listener.stateChanged(message, (int) Math.rint((((float) i) / (jobs.size() - 1)) * 100f)); stopJob(job); jobService.delete(session, job); } clip.setStatus(clip.getStatus() - profile.getStatus()); clipService.saveStatus(session, clip); profile.setStatus(0); profileService.saveStatus(session, profile); session.closeTransaction(); fireProfileUpdated(profile); fireClipUpdated(clip); for (final RenderJobDataRow job : jobs) { fireJobAborted(job); } for (final RenderJobDataRow job : jobs) { fireJobStopped(job); } for (final RenderJobDataRow job : jobs) { fireJobDeleted(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @param listener * @param message * @param percentage * @throws RenderServiceException */ public void createJobs(final int profileId, final ProgressListener listener, final String message, final float percentage) throws RenderServiceException { try { session.openTransaction(); final RenderProfileDataRow profile = profileService.getProfile(session, profileId); final RenderClipDataRow clip = clipService.getClip(session, profile.getClipId()); profile.setTotalFrames((profile.getStopTime() - profile.getStartTime()) * profile.getFrameRate()); profile.setJobFrame(0); profileService.saveFrames(session, profile); final List<RenderJobDataRow> jobs = createJobs(clip, profile, listener, message, percentage); session.closeTransaction(); fireProfileUpdated(profile); fireClipUpdated(clip); if (LibraryService.logger.isLoggable(Level.INFO)) { LibraryService.logger.info("Created " + profile.getJobCreated() + " jobs"); } for (final RenderJobDataRow job : jobs) { fireJobCreated(job); } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } private List<RenderJobDataRow> createJobs(final RenderClipDataRow clip, final RenderProfileDataRow profile, final ProgressListener listener, final String message, final float percentage) throws SessionException, DataTableException, RenderServiceException { final List<RenderJobDataRow> jobs = new ArrayList<RenderJobDataRow>(); final int nx = profile.getImageWidth() / LibraryService.TILE_WIDTH; final int ny = profile.getImageHeight() / LibraryService.TILE_HEIGHT; final int rx = profile.getImageWidth() - nx * LibraryService.TILE_WIDTH; final int ry = profile.getImageHeight() - ny * LibraryService.TILE_HEIGHT; if ((nx > 0) && (ny > 0)) { for (int i = 0; i < nx; i++) { for (int j = 0; j < ny; j++) { final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(profile.getClipName()); job.setProfileName(profile.getProfileName()); job.setClipId(profile.getClipId()); job.setProfileId(profile.getProfileId()); job.setFrameNumber(profile.getJobFrame()); job.setImageWidth(profile.getImageWidth()); job.setImageHeight(profile.getImageHeight()); job.setTileWidth(LibraryService.TILE_WIDTH); job.setTileHeight(LibraryService.TILE_HEIGHT); job.setBorderWidth(24); job.setBorderHeight(24); job.setTileOffsetX(LibraryService.TILE_WIDTH * i); job.setTileOffsetY(LibraryService.TILE_HEIGHT * j); job.setQuality(profile.getQuality()); job.setFrameRate(profile.getFrameRate()); jobs.add(job); } } } if (rx > 0) { for (int j = 0; j < ny; j++) { final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(profile.getClipName()); job.setProfileName(profile.getProfileName()); job.setClipId(profile.getClipId()); job.setProfileId(profile.getProfileId()); job.setFrameNumber(profile.getJobFrame()); job.setImageWidth(profile.getImageWidth()); job.setImageHeight(profile.getImageHeight()); job.setTileWidth(rx); job.setTileHeight(LibraryService.TILE_HEIGHT); job.setBorderWidth(24); job.setBorderHeight(24); job.setTileOffsetX(nx * LibraryService.TILE_WIDTH); job.setTileOffsetY(LibraryService.TILE_HEIGHT * j); job.setQuality(profile.getQuality()); job.setFrameRate(profile.getFrameRate()); jobs.add(job); } } if (ry > 0) { for (int i = 0; i < nx; i++) { final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(profile.getClipName()); job.setProfileName(profile.getProfileName()); job.setClipId(profile.getClipId()); job.setProfileId(profile.getProfileId()); job.setFrameNumber(profile.getJobFrame()); job.setImageWidth(profile.getImageWidth()); job.setImageHeight(profile.getImageHeight()); job.setTileWidth(LibraryService.TILE_WIDTH); job.setTileHeight(ry); job.setBorderWidth(24); job.setBorderHeight(24); job.setTileOffsetX(LibraryService.TILE_WIDTH * i); job.setTileOffsetY(ny * LibraryService.TILE_HEIGHT); job.setQuality(profile.getQuality()); job.setFrameRate(profile.getFrameRate()); jobs.add(job); } } if ((rx > 0) && (ry > 0)) { final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(profile.getClipName()); job.setProfileName(profile.getProfileName()); job.setClipId(profile.getClipId()); job.setProfileId(profile.getProfileId()); job.setFrameNumber(profile.getJobFrame()); job.setImageWidth(profile.getImageWidth()); job.setImageHeight(profile.getImageHeight()); job.setTileWidth(rx); job.setTileHeight(ry); job.setBorderWidth(24); job.setBorderHeight(24); job.setTileOffsetX(nx * LibraryService.TILE_WIDTH); job.setTileOffsetY(ny * LibraryService.TILE_HEIGHT); job.setQuality(profile.getQuality()); job.setFrameRate(profile.getFrameRate()); jobs.add(job); } profile.setJobCreated(jobs.size()); profile.setJobStored(0); profileService.saveJobs(session, profile); for (int i = 0; i < jobs.size(); i++) { RenderJobDataRow job = jobs.get(i); listener.stateChanged(message, (int) Math.rint((((float) i) / (jobs.size() - 1)) * 100f)); clip.setStatus(clip.getStatus() + 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() + 1); profileService.saveStatus(session, profile); jobService.create(session, job); startJob(job); } return jobs; } private List<RenderJobDataRow> createPostProcessJob(final RenderClipDataRow clip, final RenderProfileDataRow profile) throws SessionException, DataTableException, RenderServiceException { final List<RenderJobDataRow> jobs = new ArrayList<RenderJobDataRow>(); final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(profile.getClipName()); job.setProfileName(profile.getProfileName()); job.setClipId(profile.getClipId()); job.setProfileId(profile.getProfileId()); job.setFrameNumber(0); job.setFrameRate(profile.getFrameRate()); job.setStartTime(profile.getStartTime()); job.setStopTime(profile.getStopTime()); job.setTileWidth(profile.getImageWidth()); job.setTileHeight(profile.getImageHeight()); job.setImageWidth(profile.getImageWidth()); job.setImageHeight(profile.getImageHeight()); job.setBorderWidth(0); job.setBorderHeight(0); job.setTileOffsetX(0); job.setTileOffsetY(0); job.setJobType(JobData.POST_PROCESS_JOB); jobs.add(job); clip.setStatus(clip.getStatus() + 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() + 1); profileService.saveStatus(session, profile); jobService.create(session, job); return jobs; } private List<RenderJobDataRow> createCopyProcessJob(final RenderClipDataRow clip, final RenderProfileDataRow profile, final RenderJobDataRow processJob) throws SessionException, DataTableException, RenderServiceException { final List<RenderJobDataRow> jobs = new ArrayList<RenderJobDataRow>(); final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(processJob.getClipName()); job.setProfileName(processJob.getProfileName()); job.setClipId(processJob.getClipId()); job.setProfileId(processJob.getProfileId()); job.setFrameNumber(0); job.setFrameRate(processJob.getFrameRate()); job.setStartTime(processJob.getStartTime()); job.setStopTime(processJob.getStopTime()); job.setTileWidth(processJob.getTileWidth()); job.setTileHeight(processJob.getTileHeight()); job.setImageWidth(processJob.getImageWidth()); job.setImageHeight(processJob.getImageHeight()); job.setBorderWidth(processJob.getBorderWidth()); job.setBorderHeight(processJob.getBorderHeight()); job.setTileOffsetX(processJob.getTileOffsetX()); job.setTileOffsetY(processJob.getTileOffsetY()); job.setJobType(JobData.COPY_PROCESS_JOB); job.setJobId(processJob.getJobId()); jobs.add(job); clip.setStatus(clip.getStatus() + 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() + 1); profileService.saveStatus(session, profile); jobService.save(session, job); return jobs; } private List<RenderJobDataRow> createProcessJob(final RenderClipDataRow clip, final RenderProfileDataRow profile, final RenderJobDataRow processJob) throws SessionException, DataTableException, RenderServiceException { final List<RenderJobDataRow> jobs = new ArrayList<RenderJobDataRow>(); final RenderJobDataRow job = new RenderJobDataRow(new RenderJob()); job.setClipName(processJob.getClipName()); job.setProfileName(processJob.getProfileName()); job.setClipId(processJob.getClipId()); job.setProfileId(processJob.getProfileId()); job.setFrameNumber(processJob.getFrameNumber()); job.setFrameRate(processJob.getFrameRate()); job.setStartTime(processJob.getStartTime()); job.setStopTime(processJob.getStopTime()); job.setTileWidth(processJob.getTileWidth()); job.setTileHeight(processJob.getTileHeight()); job.setImageWidth(processJob.getImageWidth()); job.setImageHeight(processJob.getImageHeight()); job.setBorderWidth(processJob.getBorderWidth()); job.setBorderHeight(processJob.getBorderHeight()); job.setTileOffsetX(processJob.getTileOffsetX()); job.setTileOffsetY(processJob.getTileOffsetY()); job.setJobType(JobData.PROCESS_JOB); job.setJobId(processJob.getJobId()); jobs.add(job); clip.setStatus(clip.getStatus() + 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() + 1); profileService.saveStatus(session, profile); jobService.save(session, job); return jobs; } /** * @param job * @throws RenderServiceException */ public void processUpdated(final JobData jobData) throws RenderServiceException { try { session.openTransaction(); final RenderJobDataRow job = jobService.getJob(session, jobData.getJobId()); job.setFrameNumber(jobData.getFrameNumber()); jobService.saveStatus(session, job); session.closeTransaction(); fireJobUpdated(job); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void processTerminated(final JobData jobData) throws RenderServiceException { try { synchronized (session) { session.openTransaction(); final RenderJobDataRow job = jobService.getJob(session, jobData.getJobId()); final RenderClipDataRow clip = clipService.getClip(session, job.getClipId()); final RenderProfileDataRow profile = profileService.getProfile(session, job.getProfileId()); clip.setStatus(clip.getStatus() - 1); clipService.saveStatus(session, clip); profile.setStatus(profile.getStatus() - 1); profileService.saveStatus(session, profile); job.setStatus(0); jobService.saveStatus(session, job); List<RenderJobDataRow> jobs = null; job.setFrameNumber(jobData.getFrameNumber()); profile.setJobFrame(job.getFrameNumber()); profileService.saveFrames(session, profile); if (job.isCopyProcess()) { profile.setJobStored(profile.getJobStored() + 1); profileService.saveJobs(session, profile); jobService.delete(session, job); } if (job.isCopyProcess() && (profile.getJobStored() == profile.getJobCreated())) { jobs = createPostProcessJob(clip, profile); for (final RenderJobDataRow createdJob : jobs) { startJob(createdJob); } } else if (job.isProcess() && ((job.getFrameRate() == 0) || (job.getFrameNumber() == (profile.getTotalFrames() - 1)))) { jobs = createCopyProcessJob(clip, profile, job); for (final RenderJobDataRow createdJob : jobs) { startJob(createdJob); } } else if (job.isProcess()) { jobs = createProcessJob(clip, profile, job); for (final RenderJobDataRow createdJob : jobs) { startJob(createdJob); } } else if (job.isPostProcess()) { jobService.delete(session, job); } session.closeTransaction(); fireProfileUpdated(profile); fireClipUpdated(clip); fireJobDeleted(job); if (jobs != null) { for (final RenderJobDataRow createdJob : jobs) { fireJobCreated(createdJob); fireJobStarted(createdJob); } } } } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void processStarted(final JobData jobData) throws RenderServiceException { } /** * @param job * @throws RenderServiceException */ public void processStopped(final JobData jobData) throws RenderServiceException { } /** * @param job * @throws RenderServiceException */ public void processDeleted(final JobData jobData) throws RenderServiceException { // try { // synchronized (session) { // session.openTransaction(); // final RenderJobDataRow job = jobService.getJob(session, jobData.getJobId()); // if (jobData.getJobType() == JobData.COPY_PROCESS_JOB || jobData.getJobType() == JobData.POST_PROCESS_JOB) { // jobService.delete(session, job); // } // session.closeTransaction(); // if (jobData.getJobType() == JobData.COPY_PROCESS_JOB || jobData.getJobType() == JobData.POST_PROCESS_JOB) { // fireJobDeleted(job); // } // } // } // catch (final TransactionException e) { // throw new ServiceException(e); // } // catch (final Exception e) { // try { // session.abortTransaction(); // } // catch (final TransactionException x) { // x.printStackTrace(); // } // throw new ServiceException(e); // } } /** * @throws RenderServiceException */ public void deleteAll() throws RenderServiceException { try { session.openTransaction(); jobService.deleteAll(session); profileService.deleteAll(session); clipService.deleteAll(session); session.closeTransaction(); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param dataRow * @param file * @throws RenderServiceException */ public void importClip(final RenderClipDataRow dataRow, final File file) throws RenderServiceException { try { session.openTransaction(); TwisterClip clip = null; try { final TwisterClipXMLImporter importer = new TwisterClipXMLImporter(); final InputStream is = new FileInputStream(file); Document doc = XML.loadDocument(is, "twister-clip.xml"); clip = importer.importFromElement(doc.getDocumentElement()); is.close(); } catch (Exception e) { List<Extension<ConverterExtensionRuntime>> extensions = TwisterRegistry.getInstance().getConverterRegistry().getExtensionList(); for (Extension<ConverterExtensionRuntime> extension : extensions) { try { ConverterExtensionRuntime runtime = extension.createExtensionRuntime(); TwisterConfig config = runtime.createConverter().convert(file); if (config != null) { clip = new TwisterClip(); clip.addSequence(new TwisterSequence()); clip.getSequence(0).setDuration(0); clip.getSequence(0).setInitialConfig(config); } } catch (Exception x) { x.printStackTrace(); } } if (clip == null) { throw e; } } final TwisterClipController controller = new TwisterClipController(clip); controller.init(); dataRow.setDuration(controller.getDuration()); clipService.save(session, dataRow); final TwisterClipXMLExporter exporter = new TwisterClipXMLExporter(); Document doc = XML.createDocument(); final XMLNodeBuilder builder = XML.createDefaultXMLNodeBuilder(doc); final Element element = exporter.exportToElement(clip, builder); doc.appendChild(element); final OutputStream os = clipService.getOutputStream(dataRow.getClipId()); XML.saveDocument(os, "twister-clip.xml", doc); os.close(); session.closeTransaction(); fireClipLoaded(dataRow); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param dataRow * @param file * @throws RenderServiceException */ public void exportClip(final RenderClipDataRow dataRow, final File file) throws RenderServiceException { try { final TwisterClipXMLImporter importer = new TwisterClipXMLImporter(); final InputStream is = clipService.getInputStream(dataRow.getClipId()); Document doc = XML.loadDocument(is, "twister-clip.xml"); final TwisterClip clip = importer.importFromElement(doc.getDocumentElement()); is.close(); final TwisterClipXMLExporter exporter = new TwisterClipXMLExporter(); doc = XML.createDocument(); final XMLNodeBuilder builder = XML.createDefaultXMLNodeBuilder(doc); final Element element = exporter.exportToElement(clip, builder); doc.appendChild(element); final OutputStream os = new FileOutputStream(file); XML.saveDocument(os, "twister-clip.xml", doc); os.close(); } catch (final Exception e) { throw new RenderServiceException(e); } } /** * @param dataRow * @return * @throws RenderServiceException */ public TwisterClip loadClip(final RenderClipDataRow dataRow) throws RenderServiceException { try { final TwisterClipXMLImporter importer = new TwisterClipXMLImporter(); final InputStream is = clipService.getInputStream(dataRow.getClipId()); Document doc = XML.loadDocument(is, "twister-clip.xml"); final TwisterClip clip = importer.importFromElement(doc.getDocumentElement()); is.close(); return clip; } catch (final Exception e) { throw new RenderServiceException(e); } } /** * @param profile * @param encoder * @param listener * @param path * @throws RenderServiceException */ public void exportProfile(final RenderProfileDataRow profile, final EncoderExtensionRuntime<?> encoder, final ProgressListener listener, final File path) throws RenderServiceException { encoder.addProgressListener(listener); try { final EncoderContext context = new DefaultEncoderContext(profile); encoder.encode(context, path); listener.done(); } catch (final EncoderException e) { listener.failed(e); throw new RenderServiceException(e); } catch (final IOException e) { listener.failed(e); throw new RenderServiceException(e); } encoder.removeProgressListener(listener); } /** * @param listener */ public synchronized void addServiceListener(final LibraryServiceListener listener) { listeners.add(listener); } /** * @param listener */ public synchronized void removeServiceListener(final LibraryServiceListener listener) { listeners.remove(listener); } /** * @param clip */ protected synchronized void fireClipCreated(final RenderClipDataRow clip) { for (final LibraryServiceListener listener : listeners) { listener.clipCreated(clip); } } /** * @param clip */ protected synchronized void fireClipDeleted(final RenderClipDataRow clip) { for (final LibraryServiceListener listener : listeners) { listener.clipDeleted(clip); } } /** * @param clip */ protected synchronized void fireClipUpdated(final RenderClipDataRow clip) { for (final LibraryServiceListener listener : listeners) { listener.clipUpdated(clip); } } /** * @param clip */ protected synchronized void fireClipLoaded(final RenderClipDataRow clip) { for (final LibraryServiceListener listener : listeners) { listener.clipLoaded(clip); } } /** * @param profile */ protected synchronized void fireProfileCreated(final RenderProfileDataRow profile) { for (final LibraryServiceListener listener : listeners) { listener.profileCreated(profile); } } /** * @param profile */ protected synchronized void fireProfileDeleted(final RenderProfileDataRow profile) { for (final LibraryServiceListener listener : listeners) { listener.profileDeleted(profile); } } /** * @param profile */ protected synchronized void fireProfileUpdated(final RenderProfileDataRow profile) { for (final LibraryServiceListener listener : listeners) { listener.profileUpdated(profile); } } /** * @param profile */ protected synchronized void fireProfileLoaded(final RenderProfileDataRow profile) { for (final LibraryServiceListener listener : listeners) { listener.profileLoaded(profile); } } /** * @param job */ protected synchronized void fireJobCreated(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobCreated(job); } } /** * @param job */ protected synchronized void fireJobDeleted(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobDeleted(job); } } /** * @param job */ protected synchronized void fireJobUpdated(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobUpdated(job); } } /** * @param job */ protected synchronized void fireJobStarted(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobStarted(job); } } /** * @param job */ protected synchronized void fireJobAborted(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobAborted(job); } } /** * @param job */ protected synchronized void fireJobStopped(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobStopped(job); } } /** * @param job */ protected synchronized void fireJobResumed(final RenderJobDataRow job) { for (final LibraryServiceListener listener : listeners) { listener.jobResumed(job); } } /** * @param clipId * @return * @throws IOException */ public OutputStream getClipOutputStream(final int clipId) throws IOException { return clipService.getOutputStream(clipId); } /** * @param profileId * @return * @throws IOException */ public OutputStream getProfileOutputStream(final int profileId) throws IOException { return profileService.getOutputStream(profileId); } /** * @param jobId * @return * @throws IOException */ public OutputStream getJobOutputStream(final int jobId) throws IOException { return jobService.getOutputStream(jobId); } /** * @param clipId * @return * @throws IOException */ public InputStream getClipInputStream(final int clipId) throws IOException { return clipService.getInputStream(clipId); } /** * @param profileId * @return * @throws IOException */ public InputStream getProfileInputStream(final int profileId) throws IOException { return profileService.getInputStream(profileId); } /** * @param jobId * @return * @throws IOException */ public InputStream getJobInputStream(final int jobId) throws IOException { return jobService.getInputStream(jobId); } /** * @param clip * @throws RenderServiceException */ public void cleanClip(final RenderClipDataRow clip) throws RenderServiceException { try { session.openTransaction(); clipService.clean(session, clip); session.closeTransaction(); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profile * @throws RenderServiceException */ public void cleanProfile(final RenderProfileDataRow profile) throws RenderServiceException { try { session.openTransaction(); profileService.clean(session, profile); session.closeTransaction(); fireProfileUpdated(profile); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param job * @throws RenderServiceException */ public void cleanJob(final RenderJobDataRow job) throws RenderServiceException { try { session.openTransaction(); jobService.clean(session, job); session.closeTransaction(); fireJobUpdated(job); } catch (final TransactionException e) { throw new RenderServiceException(e); } catch (final Exception e) { try { session.abortTransaction(); } catch (final TransactionException x) { x.printStackTrace(); } throw new RenderServiceException(e); } } /** * @param profileId * @return * @throws IOException */ public ChunkedRandomAccessFile getProfileRandomAccessFile(final int profileId) throws IOException { return profileService.getRandomAccessFile(profileId); } /** * @param jobId * @return * @throws IOException */ public ChunkedRandomAccessFile getJobRandomAccessFile(final int jobId) throws IOException { return jobService.getRandomAccessFile(jobId); } /** * @return */ public File getWorkspace() { return workdir; } private class DefaultEncoderContext extends RAFEncoderContext { /** * @param profile * @throws IOException */ public DefaultEncoderContext(final RenderProfileDataRow profile) throws IOException { super(profileService.getRandomAccessFile(profile.getProfileId()), profile.getImageWidth(), profile.getImageHeight(), profile.getFrameRate(), (profile.getStopTime() - profile.getStartTime()) * profile.getFrameRate()); } } }