/** @param t */
  public static synchronized void remove(Trigger t) {
    int preSize = TriggerPersistence.size();

    try {
      t.unregister();
      list.remove(t);
      int postSize = TriggerPersistence.size();

      if (!(postSize == (preSize - 1))) {
        LOG.severe("Error while while removing trigger '" + t.getName() + "'");
      }
    } catch (Exception e) {
      LOG.severe("Error while while unregistering the trigger '" + t.getName() + "'");
    }
  }
Example #2
0
 protected Object unmarshalFromInputStream(
     Unmarshaller unmarshaller, InputStream is, Annotation[] anns, MediaType mt)
     throws JAXBException {
   // Try to create the read before unmarshalling the stream
   XMLStreamReader xmlReader = null;
   try {
     if (is == null) {
       Reader reader = getStreamHandlerFromCurrentMessage(Reader.class);
       if (reader == null) {
         LOG.severe("No InputStream, Reader, or XMLStreamReader is available");
         throw ExceptionUtils.toInternalServerErrorException(null, null);
       }
       xmlReader = StaxUtils.createXMLStreamReader(reader);
     } else {
       xmlReader = StaxUtils.createXMLStreamReader(is);
     }
     configureReaderRestrictions(xmlReader);
     return unmarshaller.unmarshal(xmlReader);
   } finally {
     try {
       StaxUtils.close(xmlReader);
     } catch (XMLStreamException e) {
       // Ignore
     }
   }
 }
Example #3
0
  @Override
  public String getNetworkEndpoint() {
    try {
      VdeNetworkEndpoint localEndpoint =
          new VdeNetworkEndpoint(
              NetworkUtils.getHostAddress().getHostAddress(),
              this.tempDir.toPath().resolve("sockets").toString(),
              null);
      return localEndpoint.value();
    } catch (JAXBException e) {
      LOG.severe("Could not marshal network endpoint information.");
      e.printStackTrace();

      // TODO throw BWFLAException
      return null;
    } catch (Exception e) {
      LOG.severe("Could not determine public IP address.");
      e.printStackTrace();
      return null;
    }
  }
Example #4
0
 protected void marshalToOutputStream(
     Marshaller ms, Object obj, OutputStream os, Annotation[] anns, MediaType mt)
     throws Exception {
   if (os == null) {
     Writer writer = getStreamHandlerFromCurrentMessage(Writer.class);
     if (writer == null) {
       LOG.severe("No OutputStream, Writer, or XMLStreamWriter is available");
       throw ExceptionUtils.toInternalServerErrorException(null, null);
     }
     ms.marshal(obj, writer);
     writer.flush();
   } else {
     ms.marshal(obj, os);
   }
 }
  private static boolean registerModule(
      Path pythonModuleRoot, String pythonModuleName, final String pythonClassName) {

    String pythonModuleRelPath = pythonModuleName.replace('.', '/');

    Path pythonModuleFile = pythonModuleRoot.resolve(pythonModuleRelPath + ".py");
    if (!Files.exists(pythonModuleFile)) {
      LOG.severe(String.format("Missing Python module '%s'", pythonModuleFile.toUri()));
      return false;
    }

    Path pythonInfoXmlFile = pythonModuleRoot.resolve(pythonModuleRelPath + "-info.xml");
    if (!Files.exists(pythonInfoXmlFile)) {
      LOG.warning(
          String.format(
              "Missing operator metadata file '%s'. Using defaults.", pythonInfoXmlFile.toUri()));
    }

    DefaultOperatorDescriptor operatorDescriptor =
        createOperatorDescriptor(pythonInfoXmlFile, pythonModuleName);
    File pythonModuleRootFile = FileUtils.toFile(pythonModuleRoot);

    PyOperatorSpi operatorSpi =
        new PyOperatorSpi(operatorDescriptor) {

          @Override
          public Operator createOperator() throws OperatorException {
            PyOperator pyOperator = (PyOperator) super.createOperator();

            pyOperator.setParameterDefaultValues();
            pyOperator.setPythonModulePath(pythonModuleRootFile.getPath());
            pyOperator.setPythonModuleName(pythonModuleName);
            pyOperator.setPythonClassName(pythonClassName);
            return pyOperator;
          }
        };

    String operatorName =
        operatorDescriptor.getAlias() != null
            ? operatorDescriptor.getAlias()
            : operatorDescriptor.getName();
    GPF.getDefaultInstance().getOperatorSpiRegistry().addOperatorSpi(operatorName, operatorSpi);
    LOG.info(
        String.format(
            "Python operator '%s' registered (Python module: '%s', class: '%s', root: '%s')",
            operatorName, pythonModuleName, pythonClassName, pythonModuleRootFile));
    return true;
  }
Example #6
0
  @Override
  public void destroy() {

    runner.stop();
    runner.cleanup();

    // remove temporary dir
    if (tempDir != null && tempDir.exists()) {
      try {
        FileUtils.deleteDirectory(tempDir);
        LOG.info("Temporary directory removed: " + tempDir.getAbsolutePath());
        tempDir = null;
      } catch (IOException e) {
        LOG.severe(e.getMessage());
      }
    }
  }
  /** @param t */
  public static synchronized void addAndRegister(Trigger t) {
    int preSize = TriggerPersistence.size();

    if (!list.contains(t)) {
      list.add(t);
      t.register();
      int postSize = TriggerPersistence.size();
      if (!(postSize == (preSize + 1))) {
        LOG.severe("Error while while adding and registering trigger '" + t.getName() + "'");
      }
    } else {
      // this trigger is already in the list
      int old = list.indexOf(t);
      list.get(old).unregister();
      list.set(old, t);
      t.register();
    }
  }
  /** @param folder */
  public static void saveTriggers(File folder) {
    if (list.isEmpty()) {
      LOG.warning(
          "There are no triggers to persist, "
              + folder.getAbsolutePath()
              + " will not be altered.");
      return;
    }

    if (!folder.isDirectory()) {
      LOG.warning(folder.getAbsoluteFile() + " is not a valid trigger folder. Skipped");
      return;
    }

    XStream xstream = FreedomXStream.getXstream();
    deleteTriggerFiles(folder);

    try {
      LOG.config("Saving triggers to file in " + folder.getAbsolutePath());

      for (Trigger trigger : list) {
        if (trigger.isToPersist()) {
          String uuid = trigger.getUUID();

          if ((uuid == null) || uuid.isEmpty()) {
            trigger.setUUID(UUID.randomUUID().toString());
          }

          String fileName = trigger.getUUID() + ".xtrg";
          FileWriter fstream = new FileWriter(folder + "/" + fileName);
          BufferedWriter out = new BufferedWriter(fstream);
          out.write(xstream.toXML(trigger)); // persist only the data not the logic
          // Close the output stream

          out.close();
          fstream.close();
        }
      }
    } catch (Exception e) {
      LOG.info(e.getLocalizedMessage());
      LOG.severe(Freedomotic.getStackTraceInfo(e));
    }
  }
 private static DefaultOperatorDescriptor createOperatorDescriptor(
     Path pythonInfoXmlFile, String pythonModuleName) {
   DefaultOperatorDescriptor operatorDescriptor;
   if (Files.exists(pythonInfoXmlFile)) {
     try {
       try (BufferedReader reader = Files.newBufferedReader(pythonInfoXmlFile)) {
         operatorDescriptor =
             DefaultOperatorDescriptor.fromXml(
                 reader,
                 pythonInfoXmlFile.toUri().toString(),
                 PyOperatorSpi.class.getClassLoader());
       }
     } catch (IOException e) {
       LOG.severe(String.format("Failed to read from '%s'", pythonInfoXmlFile));
       operatorDescriptor = null;
     }
   } else {
     operatorDescriptor = new DefaultOperatorDescriptor(pythonModuleName, PyOperator.class);
   }
   return operatorDescriptor;
 }
  /** @param folder */
  public static synchronized void loadTriggers(File folder) {
    XStream xstream = FreedomXStream.getXstream();

    // This filter only returns object files
    FileFilter objectFileFileter =
        new FileFilter() {
          public boolean accept(File file) {
            if (file.isFile() && file.getName().endsWith(".xtrg")) {
              return true;
            } else {
              return false;
            }
          }
        };

    File[] files = folder.listFiles(objectFileFileter);

    try {
      StringBuilder summary = new StringBuilder();
      // print an header for the index.txt file
      summary.append("#Filename \t\t #TriggerName \t\t\t #ListenedChannel").append("\n");

      if (files != null) {
        for (File file : files) {
          Trigger trigger = null;
          try {
            // validate the object against a predefined DTD
            String xml =
                DOMValidateDTD.validate(
                    file, Info.getApplicationPath() + "/config/validator/trigger.dtd");
            trigger = (Trigger) xstream.fromXML(xml);
          } catch (Exception e) {
            LOG.log(
                Level.SEVERE,
                "Trigger file {0} is not well formatted: {1}",
                new Object[] {file.getPath(), e.getLocalizedMessage()});
            continue;
          }

          // addAndRegister trigger to the list if it is not a duplicate
          if (!list.contains(trigger)) {
            if (trigger.isHardwareLevel()) {
              trigger.setPersistence(false); // it has not to me stored in root/data folder
              addAndRegister(trigger); // in the list and start listening
            } else {
              if (folder.getAbsolutePath().startsWith(Info.getPluginsPath())) {
                trigger.setPersistence(false);
              } else {
                trigger.setPersistence(true); // not hardware trigger and not plugin related
              }

              list.add(
                  trigger); // only in the list not registred. I will be registred only if used in
                            // mapping
            }
          } else {
            LOG.warning("Trigger '" + trigger.getName() + "' is already in the list");
          }

          summary
              .append(trigger.getUUID())
              .append("\t\t")
              .append(trigger.getName())
              .append("\t\t\t")
              .append(trigger.getChannel())
              .append("\n");
        }

        // writing a summary .txt file with the list of commands in this folder
        FileWriter fstream = new FileWriter(folder + "/index.txt");
        BufferedWriter indexfile = new BufferedWriter(fstream);
        indexfile.write(summary.toString());
        // Close the output stream
        indexfile.close();
      } else {
        LOG.config("No triggers to load from this folder " + folder.toString());
      }
    } catch (Exception e) {
      LOG.severe("Exception while loading this trigger.\n" + Freedomotic.getStackTraceInfo(e));
    }
  }
    /**
     * Append the range [off, off+len) from the provided sample data to the line.
     *
     * @param samples sample data
     * @param off sample data offset
     * @param len sample data length
     */
    private void appendFrames(final byte[] samples, int off, int len) {
      assert off % bytesPerFrame == 0;
      assert len % bytesPerFrame == 0;

      /* Make sure that [off, off+len) does not exceed sample's bounds */
      off = Math.min(off, (samples != null) ? samples.length : 0);

      len = Math.min(len, (samples != null) ? samples.length - off : 0);

      if (len <= 0) {
        return;
      }

      /* Convert samples if necessary */
      final byte[] samplesConverted = Arrays.copyOfRange(samples, off, off + len);

      if (convertUnsignedToSigned) {
        /* The line expects signed PCM samples, so we must
         * convert the unsigned PCM samples to signed.
         * Note that this only affects the high bytes!
         */
        for (int i = 0; i < samplesConverted.length; i += 2) {
          samplesConverted[i] = (byte) ((samplesConverted[i] & 0xff) - 0x80);
        }
      }

      /* Write samples to line */
      // final int bytesWritten = m_line.write(samplesConverted, 0, samplesConverted.length);
      final int bytesWritten = audioTrack.write(samplesConverted, 0, samplesConverted.length);

      if (bytesWritten == AudioTrack.ERROR_INVALID_OPERATION) {
        LOG.severe("Audio Track not initialized properly");
        throw new RuntimeException(
            "Audio Track not initialized properly: AudioTrack status: ERROR_INVALID_OPERATION");
      } else if (bytesWritten == AudioTrack.ERROR_BAD_VALUE) {
        LOG.severe("Wrong parameters sent to Audio Track!");
        throw new RuntimeException(
            "Wrong parameters sent to Audio Track! AudioTrack status: ERROR_BAD_VALUE");
      } else if (bytesWritten != len) {
        LOG.warning(
            "Audio output line accepted only "
                + bytesWritten
                + " bytes of sample data while trying to write "
                + samples.length
                + " bytes");
      } else {
        LOG.info(bytesWritten + " bytes written to the audio output line");
      }

      /* Update state */
      synchronized (AudioOutputQueue.this) {
        framesWrittenToLine += (bytesWritten / bytesPerFrame);

        for (int b = 0; b < bytesPerFrame; ++b) {
          lineLastFrame[b] = samples[off + len - (bytesPerFrame - b)];
        }

        if (LOG.isLoggable(Level.FINE)) {
          LOG.finest(
              "Audio output line end is now at "
                  + getNextLineTime()
                  + " after writing "
                  + len / bytesPerFrame
                  + " frames");
        }
      }
    }
    /** Enqueuer thread main method */
    @Override
    public void run() {
      try {
        /* Mute line initially to prevent clicks */
        setVolume(Float.NEGATIVE_INFINITY);

        /* Start the line */
        // m_line.start();
        // start the audio track
        audioTrack.play();

        LOG.info("Audio Track started !!!");

        boolean lineMuted = true;
        boolean didWarnGap = false;
        while (!closing) {
          if (!frameQueue.isEmpty()) {
            /* Queue filled */

            /* If the gap between the next packet and the end of line is
             * negligible (less than one packet), we write it to the line.
             * Otherwise, we fill the line buffer with silence and hope for
             * further packets to appear in the queue
             */
            final long entryFrameTime = frameQueue.firstKey();
            final long entryLineTime = convertFrameToLineTime(entryFrameTime);
            final long gapFrames = entryLineTime - getNextLineTime();

            // LOG.info("** gapFrames: " + gapFrames + " packetSizeFrames: " +  packetSizeFrames);

            if (gapFrames < -packetSizeFrames) {
              /* Too late for playback */
              LOG.warning(
                  "Audio data was scheduled for playback "
                      + (-gapFrames)
                      + " frames ago, skipping");
              frameQueue.remove(entryFrameTime);
              continue;
            } else if (gapFrames < packetSizeFrames) {
              /* Negligible gap between packet and line end. Prepare packet for playback */
              didWarnGap = false;

              /* Unmute line in case it was muted previously */
              if (lineMuted) {
                LOG.info("Audio data available, un-muting line");

                lineMuted = false;
                applyVolume();
              } else if (getVolume() != getRequestedVolume()) {
                applyVolume();
              }

              /* Get sample data and do sanity checks */
              final byte[] nextPlaybackSamples = frameQueue.remove(entryFrameTime);
              int nextPlaybackSamplesLength = nextPlaybackSamples.length;
              if (nextPlaybackSamplesLength % bytesPerFrame != 0) {
                LOG.severe(
                    "Audio data contains non-integral number of frames, ignore last "
                        + (nextPlaybackSamplesLength % bytesPerFrame)
                        + " bytes");
                nextPlaybackSamplesLength -= nextPlaybackSamplesLength % bytesPerFrame;
              }

              /* Append packet to line */
              LOG.finest(
                  "Audio data containing "
                      + nextPlaybackSamplesLength / bytesPerFrame
                      + " frames for playback time "
                      + entryFrameTime
                      + " found in queue, appending to the output line");

              appendFrames(nextPlaybackSamples, 0, nextPlaybackSamplesLength, entryLineTime);

              continue;
            } else {
              /* Gap between packet and line end. Warn */
              if (!didWarnGap) {
                didWarnGap = true;
                LOG.warning(
                    "Audio data missing for frame time "
                        + getNextLineTime()
                        + " (currently "
                        + gapFrames
                        + " frames), writing "
                        + packetSizeFrames
                        + " frames of silence");
              }
            }
          } else {
            /* Queue empty */

            if (!lineMuted) {
              lineMuted = true;
              setVolume(Float.NEGATIVE_INFINITY);
              LOG.fine(
                  "Audio data ended at frame time "
                      + getNextLineTime()
                      + ", writing "
                      + packetSizeFrames
                      + " frames of silence and muted line");
            }
          }

          appendSilence(packetSizeFrames);
        }

        // TODO: I don't think we need the appendSilence anymore when using Android API, but will
        // evaluate that later during tests
        /* Before we exit, we fill the line's buffer with silence. This should prevent
         * noise from being output while the line is being stopped
         */
        // appendSilence(m_line.available() / m_bytesPerFrame);
      } catch (final Throwable e) {
        LOG.log(Level.SEVERE, "Audio output thread died unexpectedly", e);
      } finally {
        setVolume(Float.NEGATIVE_INFINITY);
        audioTrack.stop();
        audioTrack.release();
        // m_line.stop();
        // m_line.close();
      }
    }