Package com.github.chrox.kpvbooklet

Source Code of com.github.chrox.kpvbooklet.KPVBooklet$ReaderWaitThread

package com.github.chrox.kpvbooklet;

import java.io.*;
import java.net.URI;
import java.lang.reflect.Field;
import java.io.PrintStream;

import com.github.chrox.kpvbooklet.ccadapter.CCAdapter;
import com.github.chrox.kpvbooklet.util.Log;

import com.amazon.ebook.booklet.reader.ReaderBooklet;

import com.amazon.kindle.util.lipc.LipcException;
import com.amazon.kindle.util.lipc.LipcPropertyAdapter;
import com.amazon.kindle.util.lipc.LipcPropertyProvider;
import com.amazon.kindle.util.lipc.LipcService;
import com.amazon.kindle.util.lipc.LipcSource;

/* Usage example:
     lipc-get-prop -eiq com.github.koreader.kpvbooklet.timer count
     lipc-set-prop -i com.github.koreader.kpvbooklet.timer add 1
     lipc-set-prop -i com.github.koreader.kpvbooklet.timer set 1
     lipc-set-prop -i com.github.koreader.kpvbooklet.timer reset 0
*/
class BookletTimer {
  private static final String timersource = "com.github.koreader.kpvbooklet.timer";
  private static final PrintStream logger = Log.INSTANCE;
  private static int counter = 0;
 
  private static class TimerProperties extends LipcPropertyAdapter {
    public int getIntProperty(String property) throws LipcException {
      if(property.equals("count")) {
        return counter;
      } else {
        return 0;
      }
      }
    public void setProperty(String property, int val) throws LipcException {
      if (property.equals("set")) {
        counter = val;
      } else if (property.equals("add")) {
        counter += val;
      } else if(property.equals("reset")) {
        counter = 0;
      }
      }
  }
 
  public static int getCounter() {
    return counter;
  }
 
  public static void addCounter(int count) {
    counter += count;
  }
 
    public static void addBookletCounter() {
    try {
      LipcSource source = LipcService.getInstance().createSource(timersource);
      LipcPropertyProvider timerproperty = new TimerProperties();
      source.exportIntProperty("count", timerproperty, 1);
      source.exportIntProperty("add", timerproperty, 2);
      source.exportIntProperty("set", timerproperty, 2);
      source.exportIntProperty("reset", timerproperty, 2);
     
    } catch(LipcException e) {
      logger.println("E: " + e.toString());
      e.printStackTrace(logger);
        }
  }
}

/**
* A booklet for launching koreader directly from Kindle home screen.
*
* Modified by chrox@github.
*
* @author Patric Mueller <bhaak@gmx.net>
*/
public class KPVBooklet extends ReaderBooklet {

  private final String koreader = "/mnt/us/koreader/koreader.sh";
  private final String kor_history = "/mnt/us/koreader/history/";
  private final String kpdfview = "/mnt/us/kindlepdfviewer/kpdf.sh";
  private final String kpv_history = "/mnt/us/kindlepdfviewer/history/";
 
  private Process readerProcess;
  private String history_dir;
  private CCAdapter ccrequest = CCAdapter.INSTANCE;
  private static final PrintStream logger = Log.INSTANCE;
 
  public KPVBooklet() {
    log("I: KPVBooklet");
    BookletTimer.addBookletCounter();
  }
 
  public void start(URI contentURI) { 
    log("I: start()");
    log("I: kpvbooklet launching times " + BookletTimer.getCounter());
    log("I: contentURI " + contentURI.toString());
    String path = contentURI.getPath();
    int dot = path.lastIndexOf('.');
    String ext = (dot == -1) ? "" : path.substring(dot+1).toLowerCase();
    if (ext.equals("pdf")) {
      if ( contentURI.getQuery() != null ) {
        log("I: Opening " + path + " with native reader...");
        super.start(contentURI);
        return;
      }
    }
    log("I: Opening " + path + " with koreader...");
    String[] cmd = new String[] {koreader, path};
    try {
      readerProcess = Runtime.getRuntime().exec(cmd);
      history_dir = kor_history;
    } catch (IOException e) {
      readerProcess = null;
      log("W: koreader not found, will check legacy kindlepdfviewer instead.");
    }
    // fallback to kpdf.sh if we cannot exec koreader.sh
    if (readerProcess == null) {
      log("I: Opening " + path + " with kindlepdfviewer...");
      cmd[0] = kpdfview;
      history_dir = kpv_history;
      try {
        readerProcess = Runtime.getRuntime().exec(cmd);
      } catch (IOException e) {
        log("E: " + e.toString());
      }
    }
   
    Thread thread = new ReaderWaitThread(history_dir, path);
    thread.start();
  }

  public void stop() {
    log("I: stop()");
    log("I: add kpvbooklet launching times");
    BookletTimer.addCounter(1);
    if (readerProcess != null) {
      try {
        killQuitProcess(readerProcess);
        log("I: reader process killed with return value " + readerProcess.exitValue());
      } catch (Exception e) {
        log("E: " + e.toString());
      }
    }
    super.stop();
  }
 
  /**
   * Send a QUIT signal to a process.
   *
   * See http://stackoverflow.com/questions/2950338/how-can-i-kill-a-linux-process-in-java-with-sigkill-process-destroy-does-sigte#answer-2951193
   */
  private void killQuitProcess(Process process)
    throws InterruptedException, IOException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
      Class cl = process.getClass();
      Field field = cl.getDeclaredField("pid");
      field.setAccessible(true);
      Object pidObject = field.get(process);

      Runtime.getRuntime().exec("kill -QUIT " + pidObject).waitFor();
    } else {
      throw new IllegalArgumentException("Needs to be a UNIXProcess");
    }
  }
 
  /** This thread waits for reader process to finish and then update content catalog 
   */
  class ReaderWaitThread extends Thread {
    private String history_dir = "";
    private String content_path = "";
   
    public ReaderWaitThread(String dir, String path) {
      history_dir = dir;
      content_path = path;
    }
    public void run() {
      try {
        // wait for reader process to finish
        readerProcess.waitFor();
      } catch (InterruptedException e) {
        log("E: " + e.toString());
      }
     
      try {
        // update content catlog after reader exits
        ccrequest.updateCC(content_path, extractPercentFinished(history_dir, content_path));
      } catch (Exception e) {
        log("E: " + e.toString());
      }
     
      // send backward lipc event after reader exits
      try {
        Runtime.getRuntime().exec("lipc-set-prop com.lab126.appmgrd backward 0");
      } catch (IOException e) {
        log("E: " + e.toString());
      }
    }
  }
 
  /**
   * Extract last_percent in document history file
   * @param file path
   */
  private float extractPercentFinished(String history_dir, String path) {
    float percent_finished = 0.0f;
    int slash = path.lastIndexOf('/');
    String parentname = (slash == -1) ? "" : path.substring(0, slash+1);
    String basename = (slash == -1) ? "" : path.substring(slash+1);
    String histroypath = history_dir + "[" + parentname.replace('/','#') + "] " + basename + ".lua";
    log("I: found history file: " + histroypath);
    try {
      BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(histroypath)));
      String line;
      while ((line = br.readLine()) != null) {
        if (line.indexOf("[\"percent_finished\"]") > -1) {
          log("I: found percent_finished line: " + line);
          int equal = line.lastIndexOf('=');
          int comma = line.lastIndexOf(',');
          if (equal != -1 && comma != -1) {
            String value = line.substring(equal+1, comma).trim();
            // decimal separator of number is comma in some locales
            value = value.replace(',', '.');
            percent_finished = Float.parseFloat(value) * 100;
          }
        }
        }
        br.close();
    } catch (IOException e) {
      log("E: " + e.toString());
    }
    return percent_finished;
  }
 
  private void log(String msg) {
    logger.println(msg);
  }
}
TOP

Related Classes of com.github.chrox.kpvbooklet.KPVBooklet$ReaderWaitThread

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.