/*
This file is part of JFLICKS.
JFLICKS 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.
JFLICKS 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 JFLICKS. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jflicks.tv.recorder.jhdhr;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import org.jflicks.util.Util;
import com.silicondust.libhdhomerun.HDHomerun_Channels;
import com.silicondust.libhdhomerun.HDHomerun_Device;
import com.silicondust.libhdhomerun.HDHomerun_Discover;
import com.silicondust.libhdhomerun.HDHomerun_OS;
import com.silicondust.libhdhomerun.HDHomerun_Pkt;
import com.silicondust.libhdhomerun.HDHomerun_Discover.hdhomerun_discover_device_t;
import com.silicondust.libhdhomerun.HDHomerun_Types.hdhomerun_channelscan_program_t;
import com.silicondust.libhdhomerun.HDHomerun_Types.hdhomerun_channelscan_result_t;
import com.silicondust.libhdhomerun.HDHomerun_Video;
import com.silicondust.libhdhomerun.HDHomerun_Video.hdhomerun_video_stats_t;
/**
* A class to interact with your HDHR devices on the network.
*
* @author Doug Barnum
* @version 1.0
*/
public class HDHRConfig {
private boolean scanTerminated;
private boolean saveTerminated;
/**
* Simple no argument constructor.
*/
public HDHRConfig() {
}
public HDHRDevice[] getHDHRDevices() {
HDHRDevice[] result = null;
hdhomerun_discover_device_t[] result_list = new hdhomerun_discover_device_t[64];
int count = HDHomerun_Discover.hdhomerun_discover_find_devices_custom(0,
HDHomerun_Pkt.HDHOMERUN_DEVICE_TYPE_TUNER, HDHomerun_Pkt.HDHOMERUN_DEVICE_ID_WILDCARD, result_list, 64);
if (count > 0) {
ArrayList<HDHRDevice> l = new ArrayList<HDHRDevice>();
StringBuilder value = new StringBuilder();
StringBuilder error = new StringBuilder();
for (int i = 0; i < count; i++) {
hdhomerun_discover_device_t dev = result_list[i];
String model = null;
String id = String.format("%08X", dev.device_id);
String ip = String.format("%d.%d.%d.%d", (dev.ip_addr >> 24) & 0x0FF,
(dev.ip_addr >> 16) & 0x0FF, (dev.ip_addr >> 8) & 0x0FF, (dev.ip_addr >> 0) & 0x0FF);
try {
HDHomerun_Device hd = new HDHomerun_Device(id, null);
model = hd.get_model_str();
hd.destroy();
} catch (Exception ex) {
ex.printStackTrace();
}
HDHRDevice hdhr = new HDHRDevice(id, 0, ip, model);
l.add(hdhr);
hdhr = new HDHRDevice(id, 1, ip, model);
l.add(hdhr);
}
if (l.size() > 0) {
result = l.toArray(new HDHRDevice[l.size()]);
}
}
return (result);
}
public void applyFrequency(HDHRRecorder r, String frequency) {
if (r != null) {
String device = r.getDevice();
int index = device.indexOf("-");
String id = device.substring(0, index);
String tunerStr = device.substring(index + 1);
int tuner = Util.str2int(tunerStr, 0);
String model = r.getModel();
applyFrequency(id, tuner, model, r.getConfiguredFrequencyType(), frequency);
}
}
public void applyFrequency(String id, int tuner, String model, String frequencyType, String frequency) {
if ((id != null) && (frequency != null)) {
String item = "/tuner" + tuner + "/channel";
String value = frequency;
/*
if (model != null) {
if (model.equalsIgnoreCase("hdhomeruntc_atsc")) {
value = frequencyType + ":" + value;
}
}
*/
commandSet(id, item, value);
}
}
public String streaminfo(HDHRRecorder r) {
String result = null;
if (r != null) {
String device = r.getDevice();
int index = device.indexOf("-");
String id = device.substring(0, index);
String tuner = device.substring(index + 1);
String item = "/tuner" + tuner + "/streaminfo";
String text = commandGet(id, item);
}
return (result);
}
public String streaminfo(String id, int tuner) {
String result = null;
if (id != null) {
String item = "/tuner" + tuner + "/streaminfo";
System.out.println("stream info <" + item + ">");
result = commandGet(id, item);
}
return (result);
}
public void program(HDHRRecorder r, String program) {
if (r != null) {
String device = r.getDevice();
int index = device.indexOf("-");
String id = device.substring(0, index);
String tunerStr = device.substring(index + 1);
int tuner = Util.str2int(tunerStr, 0);
program(id, tuner, program);
}
}
public void program(String id, int tuner, String program) {
if ((id != null) && (program != null)) {
String item = "/tuner" + tuner + "/program";
commandSet(id, item, program);
}
}
public void channelMap(HDHRRecorder r) {
if (r != null) {
String device = r.getDevice();
int index = device.indexOf("-");
String id = device.substring(0, index);
String tunerStr = device.substring(index + 1);
int tuner = Util.str2int(tunerStr, 0);
channelMap(id, tuner, r.getConfiguredFrequencyType());
}
}
public void channelMap(String id, int tuner, String frequencyType) {
if ((id != null) && (frequencyType != null)) {
String item = "/tuner" + tuner + "/channelmap";
commandSet(id, item, frequencyType);
}
}
public void scan(String id, int tuner, String filename) {
setScanTerminated(false);
if (id != null) {
try {
HDHomerun_Device hd = new HDHomerun_Device(id, null);
if (hd.set_tuner_from_str("" + tuner) > 0) {
StringBuilder error = new StringBuilder();
if (hd.tuner_lockkey_request(error) > 0) {
hd.set_tuner_target("none");
StringBuilder channelmap = new StringBuilder();
if (hd.get_tuner_channelmap(channelmap) > 0) {
String channelmap_scan_group =
HDHomerun_Channels.hdhomerun_channelmap_get_channelmap_scan_group(
channelmap.toString());
if ((channelmap_scan_group != null) && (channelmap_scan_group.length() > 0)) {
if (hd.channelscan_init(channelmap_scan_group) > 0) {
FileOutputStream fp = null;
if (filename != null && filename.length() > 0) {
try {
fp = new FileOutputStream(filename);
}
catch (IOException e) {
System.out.println(String.format("unable to create file: %s\n", filename));
return;
}
}
//register_signal_handlers();
int ret = 0;
while (!isScanTerminated()) { //!sigabort_flag) {
hdhomerun_channelscan_result_t result = new hdhomerun_channelscan_result_t();
ret = hd.channelscan_advance(result);
if (ret <= 0) {
break;
}
writeToFileAndScreen(fp, String.format("SCANNING: %d (%s)\n", result.frequency, result.channel_str
));
ret = hd.channelscan_detect(result);
if (ret < 0) {
break;
}
if (ret == 0) {
continue;
}
writeToFileAndScreen(fp, String.format("LOCK: %s (ss=%d snq=%d seq=%d)\n",
result.status.lock_str, result.status.signal_strength,
result.status.signal_to_noise_quality, result.status.symbol_error_quality
));
if (result.transport_stream_id_detected) {
writeToFileAndScreen(fp, String.format("TSID: 0x%04X\n", result.transport_stream_id));
}
int i;
for (i = 0; i < result.program_count; i++) {
hdhomerun_channelscan_program_t program = result.programs[i];
writeToFileAndScreen(fp, String.format("PROGRAM %s\n", program.program_str));
}
}
hd.tuner_lockkey_release();
if (fp != null) {
try {
fp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
}
}
hd.destroy();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public int save(String id, int tuner, String filename) {
int result = 0;
setSaveTerminated(false);
if ((id != null) && (filename != null)) {
try {
//HDHomerun_Debug dbg = new HDHomerun_Debug();
HDHomerun_Device hd = new HDHomerun_Device(id, null);
if (hd.set_tuner_from_str("" + tuner) <= 0) {
System.out.println("invalid tuner number\n");
return -1;
}
boolean printToConsole = false;
FileOutputStream fp = null;
if (filename.compareTo("null") == 0) {
fp = null;
} else if (filename.compareTo("-") == 0) {
printToConsole = true;
} else {
try {
fp = new FileOutputStream(filename);
} catch (FileNotFoundException e) {
System.out.println(String.format("unable to create file %s\n", filename));
return -1;
}
}
int ret = hd.stream_start();
if (ret <= 0) {
System.out.println("unable to start stream\n");
if (fp != null) {
try {
fp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return ret;
}
//register_signal_handlers(sigabort_handler, sigabort_handler, siginfo_handler);
hdhomerun_video_stats_t stats_old = new hdhomerun_video_stats_t();
hdhomerun_video_stats_t stats_cur = new hdhomerun_video_stats_t();
hd.get_video_stats(stats_old);
long next_progress = HDHomerun_OS.getcurrenttime() + 1000;
while (isSaveTerminated()) { //!sigabort_flag) {
long loop_start_time = HDHomerun_OS.getcurrenttime();
/*if (siginfo_flag) {
System.out.println("\n");
cmd_save_print_stats();
siginfo_flag = false;
}*/
int[] actual_size = new int[1];
byte[] ptr = hd.stream_recv(HDHomerun_Video.VIDEO_DATA_BUFFER_SIZE_1S, actual_size);
if (null == ptr) {
HDHomerun_OS.msleep_approx(64);
continue;
}
if (fp != null) {
try {
fp.write(ptr, 0, actual_size[0]);
}
catch(IOException e)
{
System.out.println("error writing output\n");
return -1;
}
}
else if(printToConsole)
System.out.println(String.format("Bytes Received : %d", actual_size[0]));
if (loop_start_time >= next_progress) {
next_progress += 1000;
if (loop_start_time >= next_progress) {
next_progress = loop_start_time + 1000;
}
/* Video stats. */
hd.get_video_stats(stats_cur);
if (stats_cur.overflow_error_count > stats_old.overflow_error_count) {
System.out.println("o");
} else if (stats_cur.network_error_count > stats_old.network_error_count) {
System.out.println("n");
} else if (stats_cur.transport_error_count > stats_old.transport_error_count) {
System.out.println("t");
} else if (stats_cur.sequence_error_count > stats_old.sequence_error_count) {
System.out.println("s");
} else {
System.out.println(".");
}
stats_old = stats_cur;
}
long delay = 64 - (HDHomerun_OS.getcurrenttime() - loop_start_time);
if (delay <= 0) {
continue;
}
HDHomerun_OS.msleep_approx(delay);
}
if (fp != null) {
try {
fp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
hd.stream_stop();
hd.destroy();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return result;
}
public boolean isSaveTerminated() {
return (saveTerminated);
}
public void setSaveTerminated(boolean b) {
saveTerminated = b;
}
public boolean isScanTerminated() {
return (scanTerminated);
}
public void setScanTerminated(boolean b) {
scanTerminated = b;
}
private void writeToFileAndScreen(FileOutputStream fp, String str) {
System.out.print(str);
if(fp != null) {
try {
fp.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
private String commandGet(String id, String item) {
String result = null;
if ((id != null) &&(item != null)) {
try {
HDHomerun_Device hd = new HDHomerun_Device(id, null);
StringBuilder value = new StringBuilder();
StringBuilder error = new StringBuilder();
if (hd.get_var(item, value, error) < 0) {
System.out.println("communication error sending request to hdhomerun device\n");
}
if (error.length() > 0) {
System.out.println(error);
}
hd.destroy();
result = value.toString();
System.out.println(result);
} catch (Exception ex) {
ex.printStackTrace();
}
}
return (result);
}
private void commandSet(String id, String item, String value) {
if ((id != null) &&(item != null) && (value != null)) {
try {
System.out.println("id <" + id + ">");
System.out.println("item <" + item + ">");
System.out.println("value <" + value + ">");
HDHomerun_Device hd = new HDHomerun_Device(id, null);
StringBuilder error = new StringBuilder();
if (hd.set_var(item, value, null, error) < 0) {
System.out.println("communication error sending request to hdhomerun device");
}
if (error.length() > 0) {
System.out.println(error);
}
hd.destroy();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
HDHRConfig config = new HDHRConfig();
HDHRDevice[] array = config.getHDHRDevices();
if (array != null) {
for (int i = 0; i < array.length; i++) {
System.out.println(array[i].getId() + " " + array[i].getIp() + " " + array[i].getModel());
if ((array[i].getId().equals("1032ECBE")) && (array[i].getTuner() == 0)) {
config.channelMap(array[i].getId(), 0, "us-bcast");
config.scan(array[i].getId(), array[i].getTuner(), null);
/*
config.applyFrequency(array[i].getId(), array[i].getTuner(), array[i].getModel(), "us-bcast", "19");
Thread.sleep(1000);
String output = config.streaminfo(array[i].getId(), array[i].getTuner());
System.out.println("fred <" + output + ">");
StreamInfo sinfo = new StreamInfo();
sinfo.setProgram("68.1");
System.out.println(sinfo.getProgramId(array[i].getId(), array[i].getTuner()));
*/
}
}
}
}
}