<commit_before>#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate criterion;
extern crate serialize;

use criterion::Criterion;
use std::io::{Command, File, UserDir, fs};
use std::str;

use executable::Executable;
use problem::Problem;
use solution::Solution;

mod compiler;
mod executable;
mod interpreter;
mod language;
mod problem;
mod solution;

fn lscpu() {
    match Command::new("lscpu").output() {
        Err(_) => fail!("Couldn't spawn `lscpu`"),
        Ok(po) => match str::from_utf8(po.output[]) {
            None => fail!("Couldn't parse the output of `lscpu`"),
            Some(output) => {
                let s = output.lines().filter(|line| {
                    !line.starts_with("CPU MHz:")
                }).collect::<Vec<_>>().connect("\n");

                match File::create(&Path::new("lscpu")).write_str(s.as_slice()) {
                    Err(_) => fail!("Couln't write to the cpu file"),
                    Ok(_) => {},
                }
            }
        },
    }
}

fn main() {
    let languages = language::all();

    lscpu();

    for problem in fs::readdir(&Path::new("problems")).unwrap().into_iter().filter_map(|dir| {
        Problem::new(dir)
    }) {
        let mut processed = 0u;

        for solution in languages.iter().filter_map(|language| {
            Solution::new(language, &problem)
        }) {
            match Executable::new(&solution) {
                Some(executable) => if executable.validate() == Some(true) {
                    executable.bench();
                    processed += 1;
                },
                None => {},
            }
        }

        if processed > 0 {
            Criterion::default().summarize(problem.id());

            let pid = problem.id();
            let summary_plot = Path::new(".criterion").join(pid).join("summary/new/medians.svg");
            let plots_dir = Path::new("plots");

            fs::mkdir_recursive(&plots_dir, UserDir).ok().
                expect("Couldn't create the plots directory");
            fs::copy(&summary_plot, &plots_dir.join(pid).with_extension("svg")).ok().
                expect("Couldn't copy summary plot to the plots directory");
        }
    }
}
<commit_msg>chore(main): deny all warnings<commit_after>#![deny(warnings)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;
extern crate criterion;
extern crate serialize;

use criterion::Criterion;
use std::io::{Command, File, UserDir, fs};
use std::str;

use executable::Executable;
use problem::Problem;
use solution::Solution;

mod compiler;
mod executable;
mod interpreter;
mod language;
mod problem;
mod solution;

fn lscpu() {
    match Command::new("lscpu").output() {
        Err(_) => fail!("Couldn't spawn `lscpu`"),
        Ok(po) => match str::from_utf8(po.output[]) {
            None => fail!("Couldn't parse the output of `lscpu`"),
            Some(output) => {
                let s = output.lines().filter(|line| {
                    !line.starts_with("CPU MHz:")
                }).collect::<Vec<_>>().connect("\n");

                match File::create(&Path::new("lscpu")).write_str(s.as_slice()) {
                    Err(_) => fail!("Couln't write to the cpu file"),
                    Ok(_) => {},
                }
            }
        },
    }
}

fn main() {
    let languages = language::all();

    lscpu();

    for problem in fs::readdir(&Path::new("problems")).unwrap().into_iter().filter_map(|dir| {
        Problem::new(dir)
    }) {
        let mut processed = 0u;

        for solution in languages.iter().filter_map(|language| {
            Solution::new(language, &problem)
        }) {
            match Executable::new(&solution) {
                Some(executable) => if executable.validate() == Some(true) {
                    executable.bench();
                    processed += 1;
                },
                None => {},
            }
        }

        if processed > 0 {
            Criterion::default().summarize(problem.id());

            let pid = problem.id();
            let summary_plot = Path::new(".criterion").join(pid).join("summary/new/medians.svg");
            let plots_dir = Path::new("plots");

            fs::mkdir_recursive(&plots_dir, UserDir).ok().
                expect("Couldn't create the plots directory");
            fs::copy(&summary_plot, &plots_dir.join(pid).with_extension("svg")).ok().
                expect("Couldn't copy summary plot to the plots directory");
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufReader;
use std::cmp;
use std::str::FromStr;

extern crate modfile;
use modfile::ptmf;

extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

// TODO Refactor this to several files
// TODO Move some of the functions to the modfile crate

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

static USAGE: &'static str = "
modtool.

Usage:
    modtool (-h | --help)
    modtool (-V | --version)
    modtool show [--summary] [--sample-info] [--sample-stats] [--pattern-info] <file>...
    modtool save (--number=<number> | --all) <fileprefix> <file>
    modtool remove [--unused-patterns] [--unused-samples] <fileprefix> <file>...

Options:
    -V, --version         Show version info.
    -h, --help            Show this text.

    show                  Show various info and statistics.
      --summary           Show summary info.
      --sample-info       Show info about samples.
      --sample-stats      Show sample statistics.
      --pattern-info      Show info about patterns.
      <file>              File(s) to process.

    save                  Save samples, RAW 8-bit signed.
      --all               Save all samples.
      --number=<number>   Save only sample <number>.
      <fileprefix>        Use <fileprefix> as prefix to filenames when saving.
      <file>              File to process.

    remove                Remove unused/samples and or patterns.
      --unused-patterns   Remove unused patterns.
      --unused-samples    Remove unused samples.
      <fileprefix>        Use <fileprefix> as prefix to filenames when saving.
      <file>              File(s) to process.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_file: Vec<String>,
    flag_help: bool,
	flag_version: bool,

	cmd_show: bool,
	flag_summary: bool,
    flag_sample_info: bool,
	flag_sample_stats: bool,
	flag_pattern_info: bool,

	cmd_save: bool,
	flag_all: bool,
	flag_number: String,
	arg_fileprefix: String,

	cmd_remove: bool,
	flag_unused_patterns: bool,
	flag_unused_samples: bool,
}

#[derive(Debug)]
struct Stats {
	pub min: u32,
	pub max: u32,
	pub sum: usize,
	pub avg: usize,
	pub num_values: u32
}

impl Stats {
	pub fn new() -> Stats {
		Stats{min: u32::max_value(), max: u32::min_value(), sum: 0, avg: 0, num_values: 0}
	}

	pub fn update(&mut self, val: u32) {
		self.min = cmp::min(self.min, val);
		self.max = cmp::max(self.max, val);
		self.sum += val as usize;

		self.num_values += 1;
	}

	pub fn done(&mut self) {
		self.avg = self.sum / (self.num_values as usize);
	}
}

fn show_summary(module: &ptmf::PTModule) {
	println!("Song summary");
	println!("\tSongname: {}", module.name);
	println!("\tLength: {}", module.length);
	let used_samples = module.sample_info.iter().filter(|si| si.length > 0);
	println!("\tNumber of samples with length > 0: {}", used_samples.count());
	println!("\tNumber of patterns: {}", module.patterns.len());
	println!("");
}

fn show_sample_info(module: &ptmf::PTModule) {
	let mut number = 1;
	for sample in module.sample_info.iter() {
		println!("Sample number {} details", number);
		println!("\tName: {}", sample.name);
		println!("\tLength: {}b", sample.length * 2);
		println!("\tFinetune: {}", sample.finetune);
		println!("\tVolume: {}", sample.volume);
		println!("\tRepeat start: {}b", sample.repeat_start * 2);
		println!("\tRepeat length: {}b", sample.repeat_length * 2);
		number += 1;
	}
	println!("");
}

fn show_sample_stats(module: &ptmf::PTModule) {
	let used_samples = module.sample_info.iter().filter(|si| si.length > 0);

	let mut len = Stats::new();
	let mut finetune = Stats::new();
	let mut volume = Stats::new();
	let mut repeat_start = Stats::new();
	let mut repeat_length = Stats::new();

	for sample in used_samples {
		let slen = sample.length as u32 * 2;
		let sfinetune = sample.finetune as u32;
		let svolume = sample.volume as u32;
		let srepeat_start = sample.repeat_start as u32 * 2;
		let srepeat_length = sample.repeat_length as u32 * 2;

		len.update(slen);
		finetune.update(sfinetune);
		volume.update(svolume);
		repeat_start.update(srepeat_start);
		repeat_length.update(srepeat_length);
	}

	len.done();
	finetune.done();
	volume.done();
	repeat_start.done();
	repeat_length.done();

	let unused = find_unused_samples(module);

	println!("Sample statistics");
	println!("\tLength min: {} max: {} avg: {}", len.min, len.max, len.avg);
	println!("\tFinetune min: {} max: {} avg: {}", finetune.min, finetune.max, finetune.avg);
	println!("\tVolume min: {} max: {} avg: {}", volume.min, volume.max, volume.avg);
	println!("\tRepeat start min: {} max: {} avg: {}", repeat_start.min, repeat_start.max, repeat_start.avg);
	println!("\tRepeat length min: {} max: {} avg: {}", repeat_length.min, repeat_length.max, repeat_length.avg);
	print!("\tUnused samples: ");
	for i in unused {
		print!("{} ", i);
	}
	println!("");
	println!("");
}

fn find_unused_patterns(module: &ptmf::PTModule) -> Vec<u8> {
	let mut unused:Vec<u8> = Vec::new();
	let positions = &module.positions.data[0..module.length as usize];
	let num_patterns = module.patterns.len();
	for i in 0..num_patterns as u8 {
		if !positions.contains(&i) {
			unused.push(i);
		}
	}

	unused
}

fn show_pattern_info(module: &ptmf::PTModule) {

	println!("Pattern info");
	print!("\tPattern play order: ");
	let positions = &module.positions.data[0..module.length as usize];
	for pos in positions.iter() {
		print!("{} ",pos);
	}
	println!("");

	print!("\tUnused patterns: ");
	let unused = find_unused_patterns(module);
	for i in unused {
		print!("{} ",i);
	}
	println!("");

	print!("\tEmpty patterns: ");
	for i in 0..module.patterns.len() {
		let mut empty = true;
		for row in &module.patterns[i].rows {
			for channel in &row.channels {
				if channel.period != 0 ||
					channel.sample_number != 0 ||
					channel.effect != 0 {
					empty = false;
				}
				if !empty {
					break;
				}
			}
			if !empty {
				break;
			}
		}
		if empty {
			print!("{} ",i);
		}
	}
	println!("");
}

fn save_samples(module: &ptmf::PTModule,range: &Vec<usize>,prefix: &String) {
	for i in range {
		let filename = format!("{}_{}.raw",prefix,i+1);

		let file = match File::create(&filename) {
			Ok(file) => file,
			Err(e) => {
				println!("Failed to open file: '{}' Error: '{:?}'", filename, e);
				return
			}
		};

		let mut writer = BufWriter::new(&file);
		match writer.write_all(&module.sample_data[*i]) {
			Ok(_) => (),
			Err(e) => {
				println!("Failed to write sample {}. Error: '{:?}'", i, e);
			}
		}
	}
}

fn remove_unused_patterns(module: &mut ptmf::PTModule) {
	let mut unused = find_unused_patterns(module);
	unused.reverse();

	// MUST Remove highest pattern first
	for i in unused {
		// Remove pattern
		module.patterns.remove(i as usize);

		// Adjust play positions
		for j in 0..module.length {
			let j = j as usize;
			if module.positions.data[j] > i {
				module.positions.data[j] -= 1;
			}
		}
	}
}

fn find_unused_samples(module: &ptmf::PTModule) -> Vec<u8> {
	let mut unused:Vec<u8> = Vec::new();
	let mut used = [0u8;32];

	// Find all used samples
	for pattern in &module.patterns {
		for row in &pattern.rows {
			for channel in &row.channels {
				let number = channel.sample_number as usize;
				if number > 0 {
					used[number] = 1;
				}
			}
		}
	}

	// Find all unused samples
	for i in 1..module.sample_info.len()+1 {
		if used[i] == 0 {
			unused.push(i as u8);
		}
	}

	unused
}

fn remove_unused_samples(module: &mut ptmf::PTModule) {
	let mut unused = find_unused_samples(module);
	unused.reverse();

	// MUST remove highest sample first
	for i in unused {
		let index = i as usize - 1;

		// Remove sample info and put it last
		let mut si = module.sample_info.remove(index);

		if si.length > 0 {
			// Remove sample data
			if index < module.sample_data.len() {
				module.sample_data.remove(index);
			}
		}

		si.length = 0;
		si.repeat_start = 0;
		si.repeat_length = 0;
		module.sample_info.push(si);

		// Rewrite instrument references
		// TODO optimize this
		for pattern in &mut module.patterns {
			for row in &mut pattern.rows {
				for channel in &mut row.channels {
					let number = channel.sample_number;
					if number > i {
						channel.sample_number -= 1;
					}
				}
			}
		}
	}
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
//    println!("{:?}", args);

	if args.flag_version {
		println!("Version: {}", VERSION);
		return;
	}

	if args.flag_number.len() > 0 {
		let number = usize::from_str(&args.flag_number).unwrap();
		if number < 1 || number > 31 {
			println!("Invalid sample number '{}'", number);
			return;
		}
	}

	if args.cmd_show {
		for ref filename in args.arg_file {
			let file = match File::open(filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{}'", filename, e);
					continue
				}
			};

			let mut reader = BufReader::new(&file);
			let module = match ptmf::read_mod(&mut reader) {
				Ok(module) => module,
				Err(e) => {
					println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
					continue
				}
			};

			println!("Processing: {}", filename);

			if args.flag_summary {
				show_summary(&module);
			}

			if args.flag_sample_info {
				show_sample_info(&module);
			}

			if args.flag_sample_stats {
				show_sample_stats(&module);
			}

			if args.flag_pattern_info {
				show_pattern_info(&module);
			}
		}
	} else if args.cmd_save {
		let ref filename = args.arg_file[0];
		let file = match File::open(filename) {
			Ok(file) => file,
			Err(e) => {
				println!("Failed to open file: '{}' Error: '{}'", filename, e);
				return
			}
		};

		let mut reader = BufReader::new(&file);
		let module = match ptmf::read_mod(&mut reader) {
			Ok(module) => module,
			Err(e) => {
				println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
				return
			}
		};

		println!("Processing: {}", filename);

		let range = if args.flag_all {
			0..module.sample_data.len()
		} else {
			let number = usize::from_str(&args.flag_number).unwrap() - 1;
			if number >= module.sample_data.len() {
				println!("Invalid sample number. Only {} samples available.", module.sample_data.len());
				return
			}
			number..number+1
		};

		save_samples(&module,&(range.collect()),&args.arg_fileprefix);
	} else if args.cmd_remove {
		for ref filename in args.arg_file {
			let file = match File::open(filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{}'", filename, e);
					continue
				}
			};

			let mut reader = BufReader::new(&file);
			let mut module = match ptmf::read_mod(&mut reader) {
				Ok(module) => module,
				Err(e) => {
					println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
					continue
				}
			};

			println!("Processing: {}", filename);

			if args.flag_unused_patterns {
				remove_unused_patterns(&mut module);
			}

			if args.flag_unused_samples {
				remove_unused_samples(&mut module);
			}

			let filename = format!("{}_{}",args.arg_fileprefix,filename);

			let file = match File::create(&filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{:?}'", filename, e);
					return
				}
			};

			let mut writer = BufWriter::new(&file);
			match ptmf::write_mod(&mut writer,&mut module) {
				Ok(_) => (),
				Err(e) => {
					println!("Failed to write module {}. Error: '{:?}'", filename, e);
				}
			}
		}
	}

	println!("Done!");
}
<commit_msg>Fixed. No crash on invalid sample number as seen in MOD.flasklapp<commit_after>use std::fs::File;
use std::io::BufWriter;
use std::io::Write;
use std::io::BufReader;
use std::cmp;
use std::str::FromStr;

extern crate modfile;
use modfile::ptmf;

extern crate rustc_serialize;
extern crate docopt;
use docopt::Docopt;

// TODO Refactor this to several files
// TODO Move some of the functions to the modfile crate

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

static USAGE: &'static str = "
modtool.

Usage:
    modtool (-h | --help)
    modtool (-V | --version)
    modtool show [--summary] [--sample-info] [--sample-stats] [--pattern-info] <file>...
    modtool save (--number=<number> | --all) <fileprefix> <file>
    modtool remove [--unused-patterns] [--unused-samples] <fileprefix> <file>...

Options:
    -V, --version         Show version info.
    -h, --help            Show this text.

    show                  Show various info and statistics.
      --summary           Show summary info.
      --sample-info       Show info about samples.
      --sample-stats      Show sample statistics.
      --pattern-info      Show info about patterns.
      <file>              File(s) to process.

    save                  Save samples, RAW 8-bit signed.
      --all               Save all samples.
      --number=<number>   Save only sample <number>.
      <fileprefix>        Use <fileprefix> as prefix to filenames when saving.
      <file>              File to process.

    remove                Remove unused/samples and or patterns.
      --unused-patterns   Remove unused patterns.
      --unused-samples    Remove unused samples.
      <fileprefix>        Use <fileprefix> as prefix to filenames when saving.
      <file>              File(s) to process.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_file: Vec<String>,
    flag_help: bool,
	flag_version: bool,

	cmd_show: bool,
	flag_summary: bool,
    flag_sample_info: bool,
	flag_sample_stats: bool,
	flag_pattern_info: bool,

	cmd_save: bool,
	flag_all: bool,
	flag_number: String,
	arg_fileprefix: String,

	cmd_remove: bool,
	flag_unused_patterns: bool,
	flag_unused_samples: bool,
}

#[derive(Debug)]
struct Stats {
	pub min: u32,
	pub max: u32,
	pub sum: usize,
	pub avg: usize,
	pub num_values: u32
}

impl Stats {
	pub fn new() -> Stats {
		Stats{min: u32::max_value(), max: u32::min_value(), sum: 0, avg: 0, num_values: 0}
	}

	pub fn update(&mut self, val: u32) {
		self.min = cmp::min(self.min, val);
		self.max = cmp::max(self.max, val);
		self.sum += val as usize;

		self.num_values += 1;
	}

	pub fn done(&mut self) {
		self.avg = self.sum / (self.num_values as usize);
	}
}

fn show_summary(module: &ptmf::PTModule) {
	println!("Song summary");
	println!("\tSongname: {}", module.name);
	println!("\tLength: {}", module.length);
	let used_samples = module.sample_info.iter().filter(|si| si.length > 0);
	println!("\tNumber of samples with length > 0: {}", used_samples.count());
	println!("\tNumber of patterns: {}", module.patterns.len());
	println!("");
}

fn show_sample_info(module: &ptmf::PTModule) {
	let mut number = 1;
	for sample in module.sample_info.iter() {
		println!("Sample number {} details", number);
		println!("\tName: {}", sample.name);
		println!("\tLength: {}b", sample.length * 2);
		println!("\tFinetune: {}", sample.finetune);
		println!("\tVolume: {}", sample.volume);
		println!("\tRepeat start: {}b", sample.repeat_start * 2);
		println!("\tRepeat length: {}b", sample.repeat_length * 2);
		number += 1;
	}
	println!("");
}

fn show_sample_stats(module: &ptmf::PTModule) {
	let used_samples = module.sample_info.iter().filter(|si| si.length > 0);

	let mut len = Stats::new();
	let mut finetune = Stats::new();
	let mut volume = Stats::new();
	let mut repeat_start = Stats::new();
	let mut repeat_length = Stats::new();

	for sample in used_samples {
		let slen = sample.length as u32 * 2;
		let sfinetune = sample.finetune as u32;
		let svolume = sample.volume as u32;
		let srepeat_start = sample.repeat_start as u32 * 2;
		let srepeat_length = sample.repeat_length as u32 * 2;

		len.update(slen);
		finetune.update(sfinetune);
		volume.update(svolume);
		repeat_start.update(srepeat_start);
		repeat_length.update(srepeat_length);
	}

	len.done();
	finetune.done();
	volume.done();
	repeat_start.done();
	repeat_length.done();

	let unused = find_unused_samples(module);

	println!("Sample statistics");
	println!("\tLength min: {} max: {} avg: {}", len.min, len.max, len.avg);
	println!("\tFinetune min: {} max: {} avg: {}", finetune.min, finetune.max, finetune.avg);
	println!("\tVolume min: {} max: {} avg: {}", volume.min, volume.max, volume.avg);
	println!("\tRepeat start min: {} max: {} avg: {}", repeat_start.min, repeat_start.max, repeat_start.avg);
	println!("\tRepeat length min: {} max: {} avg: {}", repeat_length.min, repeat_length.max, repeat_length.avg);
	print!("\tUnused samples: ");
	for i in unused {
		print!("{} ", i);
	}
	println!("");
	println!("");
}

fn find_unused_patterns(module: &ptmf::PTModule) -> Vec<u8> {
	let mut unused:Vec<u8> = Vec::new();
	let positions = &module.positions.data[0..module.length as usize];
	let num_patterns = module.patterns.len();
	for i in 0..num_patterns as u8 {
		if !positions.contains(&i) {
			unused.push(i);
		}
	}

	unused
}

fn show_pattern_info(module: &ptmf::PTModule) {

	println!("Pattern info");
	print!("\tPattern play order: ");
	let positions = &module.positions.data[0..module.length as usize];
	for pos in positions.iter() {
		print!("{} ",pos);
	}
	println!("");

	print!("\tUnused patterns: ");
	let unused = find_unused_patterns(module);
	for i in unused {
		print!("{} ",i);
	}
	println!("");

	print!("\tEmpty patterns: ");
	for i in 0..module.patterns.len() {
		let mut empty = true;
		for row in &module.patterns[i].rows {
			for channel in &row.channels {
				if channel.period != 0 ||
					channel.sample_number != 0 ||
					channel.effect != 0 {
					empty = false;
				}
				if !empty {
					break;
				}
			}
			if !empty {
				break;
			}
		}
		if empty {
			print!("{} ",i);
		}
	}
	println!("");
}

fn save_samples(module: &ptmf::PTModule,range: &Vec<usize>,prefix: &String) {
	for i in range {
		let filename = format!("{}_{}.raw",prefix,i+1);

		let file = match File::create(&filename) {
			Ok(file) => file,
			Err(e) => {
				println!("Failed to open file: '{}' Error: '{:?}'", filename, e);
				return
			}
		};

		let mut writer = BufWriter::new(&file);
		match writer.write_all(&module.sample_data[*i]) {
			Ok(_) => (),
			Err(e) => {
				println!("Failed to write sample {}. Error: '{:?}'", i, e);
			}
		}
	}
}

fn remove_unused_patterns(module: &mut ptmf::PTModule) {
	let mut unused = find_unused_patterns(module);
	unused.reverse();

	// MUST Remove highest pattern first
	for i in unused {
		// Remove pattern
		module.patterns.remove(i as usize);

		// Adjust play positions
		for j in 0..module.length {
			let j = j as usize;
			if module.positions.data[j] > i {
				module.positions.data[j] -= 1;
			}
		}
	}
}

fn find_unused_samples(module: &ptmf::PTModule) -> Vec<u8> {
	let mut unused:Vec<u8> = Vec::new();
	let mut used = [0u8;32];

	// Find all used samples
	for pattern_no in 0..module.patterns.len() {
		let ref pattern = module.patterns[pattern_no];
		for row_no in 0..pattern.rows.len() {
			let ref row = pattern.rows[row_no];
			for channel_no in 0..row.channels.len() {
				let ref channel = row.channels[channel_no];
				let number = channel.sample_number as usize;
				if number > 0 {
					if number > 31 {
						println!("Error: Invalid sample number in Pattern '{}' Row '{}' Channel '{}' Sample number '{}'",pattern_no,row_no,channel_no,number);
					} else {
						used[number] = 1;
					}
				}
			}
		}
	}

	// Find all unused samples
	for i in 1..module.sample_info.len()+1 {
		if used[i] == 0 {
			unused.push(i as u8);
		}
	}

	unused
}

fn remove_unused_samples(module: &mut ptmf::PTModule) {
	let mut unused = find_unused_samples(module);
	unused.reverse();

	// MUST remove highest sample first
	for i in unused {
		let index = i as usize - 1;

		// Remove sample info and put it last
		let mut si = module.sample_info.remove(index);

		if si.length > 0 {
			// Remove sample data
			if index < module.sample_data.len() {
				module.sample_data.remove(index);
			}
		}

		si.length = 0;
		si.repeat_start = 0;
		si.repeat_length = 0;
		module.sample_info.push(si);

		// Rewrite instrument references
		// TODO optimize this
		for pattern in &mut module.patterns {
			for row in &mut pattern.rows {
				for channel in &mut row.channels {
					let number = channel.sample_number;
					if number > i {
						channel.sample_number -= 1;
					}
				}
			}
		}
	}
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
//    println!("{:?}", args);

	if args.flag_version {
		println!("Version: {}", VERSION);
		return;
	}

	if args.flag_number.len() > 0 {
		let number = usize::from_str(&args.flag_number).unwrap();
		if number < 1 || number > 31 {
			println!("Invalid sample number '{}'", number);
			return;
		}
	}

	if args.cmd_show {
		for ref filename in args.arg_file {
			let file = match File::open(filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{}'", filename, e);
					continue
				}
			};

			let mut reader = BufReader::new(&file);
			let module = match ptmf::read_mod(&mut reader) {
				Ok(module) => module,
				Err(e) => {
					println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
					continue
				}
			};

			println!("Processing: {}", filename);

			if args.flag_summary {
				show_summary(&module);
			}

			if args.flag_sample_info {
				show_sample_info(&module);
			}

			if args.flag_sample_stats {
				show_sample_stats(&module);
			}

			if args.flag_pattern_info {
				show_pattern_info(&module);
			}
		}
	} else if args.cmd_save {
		let ref filename = args.arg_file[0];
		let file = match File::open(filename) {
			Ok(file) => file,
			Err(e) => {
				println!("Failed to open file: '{}' Error: '{}'", filename, e);
				return
			}
		};

		let mut reader = BufReader::new(&file);
		let module = match ptmf::read_mod(&mut reader) {
			Ok(module) => module,
			Err(e) => {
				println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
				return
			}
		};

		println!("Processing: {}", filename);

		let range = if args.flag_all {
			0..module.sample_data.len()
		} else {
			let number = usize::from_str(&args.flag_number).unwrap() - 1;
			if number >= module.sample_data.len() {
				println!("Invalid sample number. Only {} samples available.", module.sample_data.len());
				return
			}
			number..number+1
		};

		save_samples(&module,&(range.collect()),&args.arg_fileprefix);
	} else if args.cmd_remove {
		for ref filename in args.arg_file {
			let file = match File::open(filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{}'", filename, e);
					continue
				}
			};

			let mut reader = BufReader::new(&file);
			let mut module = match ptmf::read_mod(&mut reader) {
				Ok(module) => module,
				Err(e) => {
					println!("Failed to parse file: '{}' Error: '{:?}'", filename, e);
					continue
				}
			};

			println!("Processing: {}", filename);

			if args.flag_unused_patterns {
				remove_unused_patterns(&mut module);
			}

			if args.flag_unused_samples {
				remove_unused_samples(&mut module);
			}

			let filename = format!("{}_{}",args.arg_fileprefix,filename);

			let file = match File::create(&filename) {
				Ok(file) => file,
				Err(e) => {
					println!("Failed to open file: '{}' Error: '{:?}'", filename, e);
					return
				}
			};

			let mut writer = BufWriter::new(&file);
			match ptmf::write_mod(&mut writer,&mut module) {
				Ok(_) => (),
				Err(e) => {
					println!("Failed to write module {}. Error: '{:?}'", filename, e);
				}
			}
		}
	}

	println!("Done!");
}
<|endoftext|>


<commit_before>extern crate lodepng;

struct Pixel {r: u8, g: u8, b: u8}

static h : u32 = 10;
static w : u32 = 10;
static pixel_count : uint = 100;

fn main() {
    let path = &Path::new("test.png");

    let pixel_data = [Pixel {r: 0, g: 0, b: 0}, ..pixel_count];
    let mut data = [0u8, ..pixel_count*3];
    assert!(pixel_data.len()*3 == data.len());
    for (i, p) in pixel_data.iter().enumerate() {
        data[i*3 + 0] = p.r;
        data[i*3 + 1] = p.g;
        data[i*3 + 2] = p.b;
    }
    match lodepng::encode_file(path, data, w, h, lodepng::LCT_RGB, 8) {
        Err(e) => fail!("Error writing: {}", e),
        Ok(_)  => (),
    }
}
<commit_msg>Base number of pixels on the width and the height<commit_after>extern crate lodepng;

struct Pixel {r: u8, g: u8, b: u8}

static h : u32 = 10;
static w : u32 = 10;
static pixel_count : uint = (w*h) as uint;

fn main() {
    let path = &Path::new("test.png");

    let pixel_data = [Pixel {r: 0, g: 0, b: 0}, ..pixel_count];
    let mut data = [0u8, ..pixel_count*3u];
    assert!(pixel_data.len()*3 == data.len());
    for (i, p) in pixel_data.iter().enumerate() {
        data[i*3 + 0] = p.r;
        data[i*3 + 1] = p.g;
        data[i*3 + 2] = p.b;
    }
    match lodepng::encode_file(path, data, w, h, lodepng::LCT_RGB, 8) {
        Err(e) => fail!("Error writing: {}", e),
        Ok(_)  => (),
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]

extern crate cjdrs;
extern crate mio;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;
#[phase(plugin)] extern crate docopt_macros;

#[cfg(not(test))] use docopt::Docopt;
#[cfg(not(test))] use cjdrs::Config;
#[cfg(not(test))] use cjdrs::{PrivateKey, PrivateIdentity};
#[cfg(not(test))] use cjdrs::interface;
#[cfg(not(test))] use cjdrs::Router;
#[cfg(not(test))] use cjdrs::EventHandler;

docopt!(Args deriving Show, "
Usage: cjdrs --help
       cjdrs init [--cfg=<file>]
       cjdrs run [--cfg=<file>]

Options:
  -h, --help      Show this message.
  --cfg=<file>    Configuration file [default: cjdrs.conf]

1. Run 'cjdrs init' to generate a configuration file.
2. Edit the configuration file as needed.
2. Run 'cjdrs run' to start cjdrs.

Configuration file defaults to 'cjdrs.conf' if not given.
");

#[cfg(not(test))]
fn main() {
	let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
	let config_path = Path::new(args.flag_cfg);

	cjdrs::init();

	// Generate new configuraion file
	if args.cmd_init {
		let identity = PrivateIdentity::generate();

		let config = Config::get_default(&identity);
		config.write(&config_path).unwrap();

		println!("Created new configuration file '{}'", config_path.display());
		println!("Public key: {}", identity.public_key.as_string());
		println!("Address:    {}", identity.address);
		return;
	}

	// Otherwise continue running
	assert!(args.cmd_run);

	let config = Config::load(&config_path);
	let identity = {
		let private_key = PrivateKey::from_string(config.privateKey.as_slice()).unwrap();
		PrivateIdentity::from_private_key(&private_key).unwrap()
	};

	println!("Public key:  {}", identity.public_key.as_string());
	println!("Address:     {}", identity.address);

	let tun_interface = interface::Tun::new(
		config.tunDevice.as_slice(),
		&identity.address);
	println!("Opened tun device '{}'", tun_interface.get_name());

	let udp_interface = interface::Udp::create(config.udpBind.as_slice());

	let router = Router::new(&identity.address);

	let mut mio_loop: mio::EventLoop<uint, ()> = mio::EventLoop::new().unwrap();
	let event_handler = EventHandler::new(&mut mio_loop,
		identity,
		tun_interface,
		udp_interface,
		router).ok().expect("Couldn't create the event handler");

	if let Err(e) = mio_loop.run(event_handler) {
		panic!("Error while running event loop: {}", e.error);
	}
}
<commit_msg>Divide different commands into different functions in main()<commit_after>#![feature(phase)]

extern crate cjdrs;
extern crate mio;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;
#[phase(plugin)] extern crate docopt_macros;

#[cfg(not(test))] use docopt::Docopt;
#[cfg(not(test))] use cjdrs::Config;
#[cfg(not(test))] use cjdrs::{PrivateKey, PrivateIdentity};
#[cfg(not(test))] use cjdrs::interface;
#[cfg(not(test))] use cjdrs::Router;
#[cfg(not(test))] use cjdrs::EventHandler;

docopt!(Args deriving Show, "
Usage: cjdrs --help
       cjdrs init [--cfg=<file>]
       cjdrs run [--cfg=<file>]

Options:
  -h, --help      Show this message.
  --cfg=<file>    Configuration file [default: cjdrs.conf]

1. Run 'cjdrs init' to generate a configuration file.
2. Edit the configuration file as needed.
2. Run 'cjdrs run' to start cjdrs.

Configuration file defaults to 'cjdrs.conf' if not given.
");

#[cfg(not(test))]
fn main() {
	let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit());
	let config_path = Path::new(args.flag_cfg);

	cjdrs::init();

	if args.cmd_init {
		init_config(&config_path);
	} else {
		assert!(args.cmd_run);
		let config = Config::load(&config_path);
		run(&config);
	}
}

#[cfg(not(test))]
fn init_config(config_path: &Path) {
	let identity = PrivateIdentity::generate();

	let config = Config::get_default(&identity);
	config.write(config_path).unwrap();

	println!("Created a new configuration file '{}'", config_path.display());
	println!("Public key: {}", identity.public_key.as_string());
	println!("Address:    {}", identity.address);
}

#[cfg(not(test))]
fn run(config: &Config) {
	let my_identity = {
		let private_key = PrivateKey::from_string(config.privateKey.as_slice()).unwrap();
		PrivateIdentity::from_private_key(&private_key).unwrap()
	};

	println!("Public key: {}", my_identity.public_key.as_string());
	println!("Address:    {}", my_identity.address);

	let tun_interface = interface::Tun::new(
		config.tunDevice.as_slice(),
		&my_identity.address);
	println!("Opened tun device '{}'", tun_interface.get_name());

	let udp_interface = interface::Udp::create(config.udpBind.as_slice());

	let router = Router::new(&my_identity.address);

	let mut mio_loop: mio::EventLoop<uint, ()> = mio::EventLoop::new().unwrap();
	let event_handler = EventHandler::new(&mut mio_loop,
		my_identity,
		tun_interface,
		udp_interface,
		router).ok().expect("Couldn't create the event handler");

	if let Err(e) = mio_loop.run(event_handler) {
		panic!("Error while running event loop: {}", e.error);
	}
}
<|endoftext|>


<commit_before>// TODO: (Optional) Add theme system
// TODO: (Optional) Add globals with theme system
// TODO: Recover gracefully from errors
extern crate walkdir;
extern crate tera;
extern crate toml;

mod templates;
mod dotfiles;

use toml::Parser;
use std::fs::File;
use std::io::Read;
use std::process::exit;
use std::env::{current_exe, home_dir, args};

fn main() {
    let home_dir = home_dir().unwrap();
    let home_dir = home_dir.to_str().unwrap();
    let mut app_dir = current_exe().unwrap();
    app_dir.pop();
    let app_dir = app_dir.to_str().unwrap();

    let mut buffer = String::new();
    let _ = match File::open(format!("{}/config.toml", app_dir).as_str()) {
        Ok(mut f) => f.read_to_string(&mut buffer),
        Err(_) => {
            println!("Could not open config file.");
            exit(1);
        }
    };

    let config = match Parser::new(&buffer).parse() {
        Some(config) => config,
        None => {
            println!("error: could not parse configuration file");
            exit(1);
        }
    };

    let args: Vec<_> = args().collect();
    if args.len() == 1 || args[1] == "--templates" {
        templates::load(home_dir, app_dir, &config);
    }
    if args.len() == 1 || args[1] == "--dotfiles" {
        dotfiles::load(home_dir, app_dir, &config);
    }
}
<commit_msg>Updated TODO.<commit_after>// TODO: (Optional) Add theme system
// TODO: (Optional) Add globals with theme system
extern crate walkdir;
extern crate tera;
extern crate toml;

mod templates;
mod dotfiles;

use toml::Parser;
use std::fs::File;
use std::io::Read;
use std::process::exit;
use std::env::{current_exe, home_dir, args};

fn main() {
    let home_dir = home_dir().unwrap();
    let home_dir = home_dir.to_str().unwrap();
    let mut app_dir = current_exe().unwrap();
    app_dir.pop();
    let app_dir = app_dir.to_str().unwrap();

    let mut buffer = String::new();
    let _ = match File::open(format!("{}/config.toml", app_dir).as_str()) {
        Ok(mut f) => f.read_to_string(&mut buffer),
        Err(_) => {
            println!("Could not open config file.");
            exit(1);
        }
    };

    let config = match Parser::new(&buffer).parse() {
        Some(config) => config,
        None => {
            println!("error: could not parse configuration file");
            exit(1);
        }
    };

    let args: Vec<_> = args().collect();
    if args.len() == 1 || args[1] == "--templates" {
        templates::load(home_dir, app_dir, &config);
    }
    if args.len() == 1 || args[1] == "--dotfiles" {
        dotfiles::load(home_dir, app_dir, &config);
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    // editor source - either a filename or stdin
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    let source = if unsafe { libc::isatty(libc::STDIN_FILENO) == 1 } {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        // FIXME: find a way to do this without unsafe
        //        std::io doesn't allow for this, currently
        buffer_stderr: unsafe { libc::isatty(libc::STDERR_FILENO) == 1 },
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<commit_msg>Refactor usage of libc<commit_after>#![feature(libc)]
#![feature(io)]
#![cfg(not(test))]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate rustbox;
extern crate docopt;
extern crate iota;

use std::io::stdin;
use docopt::Docopt;
use iota::{
    Editor, Input,
    StandardMode, NormalMode,
    RustboxFrontend, Mode
};
use rustbox::{InitOptions, RustBox, InputMode};
static USAGE: &'static str = "
Usage: iota [<filename>] [options]
       iota --help

Options:
    --vi           Start Iota with vi-like modes
    -h, --help     Show this message.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_filename: Option<String>,
    flag_vi: bool,
    flag_help: bool,
}

fn is_raw(fileno: libc::c_int) -> bool {
    // FIXME: find a way to do this without unsafe
    //        std::io doesn't allow for this, currently
    unsafe { libc::isatty(fileno) == 1 }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    let stdin_is_raw = is_raw(libc::STDIN_FILENO);
    let stderr_is_raw = is_raw(libc::STDERR_FILENO);

    // editor source - either a filename or stdin
    let source = if stdin_is_raw {
        Input::Filename(args.arg_filename)
    } else {
        Input::Stdin(stdin())
    };

    // initialise rustbox
    let rb = match RustBox::init(InitOptions{
        // FIXME: find a way to do this without unsafe
        //        std::io doesn't allow for this, currently
        buffer_stderr: stderr_is_raw,
        input_mode: InputMode::Esc,
    }) {
        Result::Ok(v) => v,
        Result::Err(e) => panic!("{}", e),
    };

    // initialise the frontend
    let frontend = RustboxFrontend::new(&rb);

    // initialise the editor mode
    let mode: Box<Mode> = if args.flag_vi {
        Box::new(NormalMode::new())
    } else {
         Box::new(StandardMode::new())
    };

    // start the editor
    let mut editor = Editor::new(source, mode, frontend);
    editor.start();
}
<|endoftext|>


<commit_before>extern crate connectr;
use connectr::SpotifyResponse;
use connectr::TStatusBar;
use connectr::MenuItem;
use connectr::NSCallback;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::env;
use std::ptr;
use std::thread::sleep;
use std::time::Duration;
use std::sync::mpsc::channel;

extern crate time;

extern crate rustc_serialize;
use rustc_serialize::json;

// How often to refresh Spotify state (if nothing triggers a refresh earlier).
pub const REFRESH_PERIOD: i64 = 30;

#[derive(RustcDecodable, RustcEncodable, Debug)]
enum CallbackAction {
    SelectDevice,
    PlayPause,
    SkipNext,
    SkipPrev,
    Volume,
    Preset,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct MenuCallbackCommand {
    action: CallbackAction,
    sender: u64,
    data: String,
}

#[cfg(target_os = "macos")]
use connectr::osx;

struct MenuItems {
    device: Vec<(MenuItem, String)>,
    play: MenuItem,
    next: MenuItem,
    prev: MenuItem,
    preset: Vec<MenuItem>,
    volume: Vec<MenuItem>,
}
struct ConnectrApp {
    menu: MenuItems,
    device_list: Option<connectr::ConnectDeviceList>,
    player_state: Option<connectr::PlayerState>,
}

fn play_action_label(is_playing: bool) -> &'static str {
    match is_playing {
        true => "Pause",
        false => "Play",
    }
}

fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp, spotify: &mut connectr::SpotifyConnectr, status: &mut T) {
    app.device_list = Some(spotify.request_device_list());
    app.player_state = Some(spotify.request_player_state());
    let ref device_list = app.device_list.as_ref().unwrap();
    let ref player_state = app.player_state.as_ref().unwrap();

    println!("Playback State:\n{}", player_state);
    let play_str = format!("{: ^50}\n{: ^50}\n{: ^50}",
                           &player_state.item.name,
                           &player_state.item.artists[0].name,
                           &player_state.item.album.name);
    status.set_tooltip(&play_str);

    status.add_label("Now Playing:");
    status.add_separator();
    //status.add_label(&player_state.item.name);
    status.add_label(&format!("{:<50}", &player_state.item.name));
    status.add_label(&format!("{:<50}", &player_state.item.artists[0].name));
    status.add_label(&format!("{:<50}", &player_state.item.album.name));
    let ms = player_state.item.duration_ms;
    let min = ms / 1000 / 60;
    let sec = (ms - (min * 60 * 1000)) / 1000;
    status.add_label(&format!("{:<50}", format!("{}:{:02}", min, sec)));

    status.add_label("");
    status.add_label("Actions:");
    status.add_separator();
    {
        let play_str = play_action_label(player_state.is_playing);
        let is_playing = player_state.is_playing.clone();
        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::PlayPause,
                sender: sender,
                data: is_playing.to_string(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.play = status.add_item(&play_str, cb, false);

        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SkipNext,
                sender: sender,
                data: String::new(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.next = status.add_item("Next", cb, false);

        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SkipPrev,
                sender: sender,
                data: String::new(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.prev = status.add_item("Previous", cb, false);
    }

    status.add_label("");
    status.add_label("Presets:");
    status.add_separator();
    {
        let presets = spotify.get_presets();
        for preset in presets {
            let ref name = preset.0;
            let uri = preset.1.clone();
            let cb: NSCallback = Box::new(move |sender, tx| {
                let cmd = MenuCallbackCommand {
                    action: CallbackAction::Preset,
                    sender: sender,
                    data: uri.to_owned(),
                };
                let _ = tx.send(json::encode(&cmd).unwrap());
            });
            let item = status.add_item(&name.clone(), cb, false);
            app.menu.preset.push(item);
        }
    }

    status.add_label("");
    status.add_label("Devices:");
    status.add_separator();
    println!("Visible Devices:");
    let mut cur_volume: u32 = 0;
    for dev in *device_list {
        println!("{}", dev);
        let id = dev.id.clone();
        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SelectDevice,
                sender: sender,
                data: id.to_owned(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        let item = status.add_item(&dev.name, cb, dev.is_active);
        if dev.is_active {
            cur_volume = match dev.volume_percent {
                Some(v) => {
                    (v as f32 / 10.0).round() as u32 * 10
                },
                None => 100,
            }
        }
        app.menu.device.push((item, dev.id.clone()));
    }
    println!("");

    status.add_label("");
    status.add_label("Volume:");
    status.add_separator();
    {
        let mut i = 0;
        while i <= 100 {
            let vol_str = format!("{}%", i);
            let cb: NSCallback = Box::new(move |sender, tx| {
                let cmd = MenuCallbackCommand {
                    action: CallbackAction::Volume,
                    sender: sender,
                    data: i.to_string(),
                };
                let _ = tx.send(json::encode(&cmd).unwrap());
            });
            let item = status.add_item(&vol_str, cb, i == cur_volume);
            app.menu.volume.push(item);
            i += 10;
        }
    }
    status.add_separator();
    status.add_quit("Exit");
}

fn clear_menu<T: TStatusBar>(app: &mut ConnectrApp, _: &mut connectr::SpotifyConnectr, status: &mut T) {
    app.menu = MenuItems {
        device: Vec::<(MenuItem, String)>::new(),
        play: ptr::null_mut(),
        next: ptr::null_mut(),
        prev: ptr::null_mut(),
        preset: Vec::<MenuItem>::new(),
        volume: Vec::<MenuItem>::new(),
    };
    status.clear_items();
}

fn create_logger() {
    use log::LogLevelFilter;
    use log4rs::append::console::ConsoleAppender;
    use log4rs::append::file::FileAppender;
    use log4rs::encode::pattern::PatternEncoder;
    use log4rs::config::{Appender, Config, Logger, Root};

    let log_path = format!("{}/{}", env::home_dir().unwrap().display(), ".connectr.log");
    let stdout = ConsoleAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{m}{n}")))
        .build();
    let requests = FileAppender::builder()
        .build(&log_path)
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .appender(Appender::builder().build("requests", Box::new(requests)))
        .logger(Logger::builder().build("app::backend::db", LogLevelFilter::Info))
        .logger(Logger::builder()
            .appender("requests")
            .additive(false)
            .build("app::requests", LogLevelFilter::Info))
        .build(Root::builder().appender("stdout").appender("requests").build(LogLevelFilter::Info))
        .unwrap();
    let _ = log4rs::init_config(config).unwrap();
}

fn handle_callback<T: TStatusBar>(app: &mut ConnectrApp, spotify: &mut connectr::SpotifyConnectr,
                   status: &mut T, cmd: &MenuCallbackCommand) {
    info!("Executed action: {:?}", cmd.action);
    match cmd.action {
        CallbackAction::SelectDevice => {
            let device = &app.menu.device;
            for dev in device {
                let &(ref item, _) = dev;
                status.unsel_item(*item as u64);
            }
            status.sel_item(cmd.sender);
            // Spotify is broken.  Must be 'true', always starts playing.
            require(spotify.transfer(cmd.data.clone(), true));
        },
        CallbackAction::PlayPause => {
            let player_state = spotify.request_player_state();
            match player_state.is_playing {
                true => {require(spotify.pause());},
                false => {require(spotify.play(None));},
            }
            let play_str = play_action_label(!player_state.is_playing);
            status.update_item(app.menu.play, play_str);
        },
        CallbackAction::Preset => {
            play_uri(spotify, None, Some(&cmd.data));
        }
        CallbackAction::SkipNext => {
            require(spotify.next());
        }
        CallbackAction::SkipPrev => {
            require(spotify.previous());
        }
        CallbackAction::Volume => {
            let vol = cmd.data.parse::<u32>().unwrap();
            require(spotify.volume(vol));
            let volume = &app.menu.volume;
            for item in volume {
                status.unsel_item(*item as u64);
            }
            status.sel_item(cmd.sender);
        }
    }
}

fn refresh_time(app: &mut ConnectrApp, now: i64) -> i64 {
    let refresh_offset = match app.player_state.as_ref() {
        Some(ref state) => {
            match state.is_playing {
                true => {
                    let track_end = match state.progress_ms {
                        Some(prog) => state.item.duration_ms - prog,
                        None => state.item.duration_ms,
                    } as i64;
                    // Refresh 1 second after track ends
                    track_end/1000 + 1
                },
                false => REFRESH_PERIOD,
            }
        }
        None => REFRESH_PERIOD,
    };
    println!("State refresh in {} seconds.", refresh_offset);
    now + std::cmp::min(REFRESH_PERIOD, refresh_offset) as i64
}

fn main() {
    create_logger();
    info!("Started Connectr");

    let mut app = ConnectrApp {
        menu: MenuItems {
            device: Vec::<(MenuItem, String)>::new(),
            play: ptr::null_mut(),
            next: ptr::null_mut(),
            prev: ptr::null_mut(),
            preset: Vec::<MenuItem>::new(),
            volume: Vec::<MenuItem>::new(),
        },
        device_list: None,
        player_state: None,
    };
    let mut refresh_time_utc = 0;
    let (tx,rx) = channel::<String>();
    let mut spotify = connectr::SpotifyConnectr::new();
    info!("Created Spotify controller.");
    spotify.connect();
    info!("Created Spotify connection.");
    spotify.set_target_device(None);
    #[cfg(target_os = "macos")]
    let mut status = osx::OSXStatusBar::new(tx);
    info!("Created status bar.");
    #[cfg(not(target_os = "macos"))]
    let mut status = connectr::DummyStatusBar::new(tx);

    loop {
        let now = time::now_utc().to_timespec().sec as i64;
        if now > refresh_time_utc {
            // Redraw the whole menu once every 60 seconds, or sooner if a
            // command is processed later.
            clear_menu(&mut app, &mut spotify, &mut status);
            fill_menu(&mut app, &mut spotify, &mut status);
            refresh_time_utc = refresh_time(&mut app, now);
            info!("Refreshed Spotify state.");
        }

        spotify.await_once(false);
        if let Ok(s) = rx.try_recv() {
            println!("Received {}", s);
            let cmd: MenuCallbackCommand = json::decode(&s).unwrap();
            handle_callback(&mut app, &mut spotify, &mut status, &cmd);
            refresh_time_utc = now + 1;
        }
        status.run(false);
        sleep(Duration::from_millis(10));
    }
}

fn require(response: SpotifyResponse) {
    match response.code.unwrap() {
        200 ... 299 => (),
        _ => panic!("{}", response)
    }
    println!("Response: {}", response.code.unwrap());
}

fn play_uri(spotify: &mut connectr::SpotifyConnectr, device: Option<&str>, uri: Option<&str>) {
    match device {
        Some(dev) => { spotify.set_target_device(Some(dev.to_string())); },
        None => { spotify.set_target_device(None); },
    }
    match uri {
        Some(s) => {
            let ctx = connectr::PlayContext::new()
                .context_uri(s)
                .offset_position(0)
                .build();
            require(spotify.play(Some(&ctx)));
        }
        None => {
            println!("Transfer!");
            require(spotify.play(None));
        }
    };
}
<commit_msg>Fix integer overflow in refresh time calculation<commit_after>extern crate connectr;
use connectr::SpotifyResponse;
use connectr::TStatusBar;
use connectr::MenuItem;
use connectr::NSCallback;

#[macro_use]
extern crate log;
extern crate log4rs;

use std::env;
use std::ptr;
use std::thread::sleep;
use std::time::Duration;
use std::sync::mpsc::channel;

extern crate time;

extern crate rustc_serialize;
use rustc_serialize::json;

// How often to refresh Spotify state (if nothing triggers a refresh earlier).
pub const REFRESH_PERIOD: i64 = 30;

#[derive(RustcDecodable, RustcEncodable, Debug)]
enum CallbackAction {
    SelectDevice,
    PlayPause,
    SkipNext,
    SkipPrev,
    Volume,
    Preset,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
struct MenuCallbackCommand {
    action: CallbackAction,
    sender: u64,
    data: String,
}

#[cfg(target_os = "macos")]
use connectr::osx;

struct MenuItems {
    device: Vec<(MenuItem, String)>,
    play: MenuItem,
    next: MenuItem,
    prev: MenuItem,
    preset: Vec<MenuItem>,
    volume: Vec<MenuItem>,
}
struct ConnectrApp {
    menu: MenuItems,
    device_list: Option<connectr::ConnectDeviceList>,
    player_state: Option<connectr::PlayerState>,
}

fn play_action_label(is_playing: bool) -> &'static str {
    match is_playing {
        true => "Pause",
        false => "Play",
    }
}

fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp, spotify: &mut connectr::SpotifyConnectr, status: &mut T) {
    app.device_list = Some(spotify.request_device_list());
    app.player_state = Some(spotify.request_player_state());
    let ref device_list = app.device_list.as_ref().unwrap();
    let ref player_state = app.player_state.as_ref().unwrap();

    println!("Playback State:\n{}", player_state);
    let play_str = format!("{: ^50}\n{: ^50}\n{: ^50}",
                           &player_state.item.name,
                           &player_state.item.artists[0].name,
                           &player_state.item.album.name);
    status.set_tooltip(&play_str);

    status.add_label("Now Playing:");
    status.add_separator();
    //status.add_label(&player_state.item.name);
    status.add_label(&format!("{:<50}", &player_state.item.name));
    status.add_label(&format!("{:<50}", &player_state.item.artists[0].name));
    status.add_label(&format!("{:<50}", &player_state.item.album.name));
    let ms = player_state.item.duration_ms;
    let min = ms / 1000 / 60;
    let sec = (ms - (min * 60 * 1000)) / 1000;
    status.add_label(&format!("{:<50}", format!("{}:{:02}", min, sec)));

    status.add_label("");
    status.add_label("Actions:");
    status.add_separator();
    {
        let play_str = play_action_label(player_state.is_playing);
        let is_playing = player_state.is_playing.clone();
        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::PlayPause,
                sender: sender,
                data: is_playing.to_string(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.play = status.add_item(&play_str, cb, false);

        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SkipNext,
                sender: sender,
                data: String::new(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.next = status.add_item("Next", cb, false);

        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SkipPrev,
                sender: sender,
                data: String::new(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        app.menu.prev = status.add_item("Previous", cb, false);
    }

    status.add_label("");
    status.add_label("Presets:");
    status.add_separator();
    {
        let presets = spotify.get_presets();
        for preset in presets {
            let ref name = preset.0;
            let uri = preset.1.clone();
            let cb: NSCallback = Box::new(move |sender, tx| {
                let cmd = MenuCallbackCommand {
                    action: CallbackAction::Preset,
                    sender: sender,
                    data: uri.to_owned(),
                };
                let _ = tx.send(json::encode(&cmd).unwrap());
            });
            let item = status.add_item(&name.clone(), cb, false);
            app.menu.preset.push(item);
        }
    }

    status.add_label("");
    status.add_label("Devices:");
    status.add_separator();
    println!("Visible Devices:");
    let mut cur_volume: u32 = 0;
    for dev in *device_list {
        println!("{}", dev);
        let id = dev.id.clone();
        let cb: NSCallback = Box::new(move |sender, tx| {
            let cmd = MenuCallbackCommand {
                action: CallbackAction::SelectDevice,
                sender: sender,
                data: id.to_owned(),
            };
            let _ = tx.send(json::encode(&cmd).unwrap());
        });
        let item = status.add_item(&dev.name, cb, dev.is_active);
        if dev.is_active {
            cur_volume = match dev.volume_percent {
                Some(v) => {
                    (v as f32 / 10.0).round() as u32 * 10
                },
                None => 100,
            }
        }
        app.menu.device.push((item, dev.id.clone()));
    }
    println!("");

    status.add_label("");
    status.add_label("Volume:");
    status.add_separator();
    {
        let mut i = 0;
        while i <= 100 {
            let vol_str = format!("{}%", i);
            let cb: NSCallback = Box::new(move |sender, tx| {
                let cmd = MenuCallbackCommand {
                    action: CallbackAction::Volume,
                    sender: sender,
                    data: i.to_string(),
                };
                let _ = tx.send(json::encode(&cmd).unwrap());
            });
            let item = status.add_item(&vol_str, cb, i == cur_volume);
            app.menu.volume.push(item);
            i += 10;
        }
    }
    status.add_separator();
    status.add_quit("Exit");
}

fn clear_menu<T: TStatusBar>(app: &mut ConnectrApp, _: &mut connectr::SpotifyConnectr, status: &mut T) {
    app.menu = MenuItems {
        device: Vec::<(MenuItem, String)>::new(),
        play: ptr::null_mut(),
        next: ptr::null_mut(),
        prev: ptr::null_mut(),
        preset: Vec::<MenuItem>::new(),
        volume: Vec::<MenuItem>::new(),
    };
    status.clear_items();
}

fn create_logger() {
    use log::LogLevelFilter;
    use log4rs::append::console::ConsoleAppender;
    use log4rs::append::file::FileAppender;
    use log4rs::encode::pattern::PatternEncoder;
    use log4rs::config::{Appender, Config, Logger, Root};

    let log_path = format!("{}/{}", env::home_dir().unwrap().display(), ".connectr.log");
    let stdout = ConsoleAppender::builder()
        .encoder(Box::new(PatternEncoder::new("{m}{n}")))
        .build();
    let requests = FileAppender::builder()
        .build(&log_path)
        .unwrap();

    let config = Config::builder()
        .appender(Appender::builder().build("stdout", Box::new(stdout)))
        .appender(Appender::builder().build("requests", Box::new(requests)))
        .logger(Logger::builder().build("app::backend::db", LogLevelFilter::Info))
        .logger(Logger::builder()
            .appender("requests")
            .additive(false)
            .build("app::requests", LogLevelFilter::Info))
        .build(Root::builder().appender("stdout").appender("requests").build(LogLevelFilter::Info))
        .unwrap();
    let _ = log4rs::init_config(config).unwrap();
}

fn handle_callback<T: TStatusBar>(app: &mut ConnectrApp, spotify: &mut connectr::SpotifyConnectr,
                   status: &mut T, cmd: &MenuCallbackCommand) {
    info!("Executed action: {:?}", cmd.action);
    match cmd.action {
        CallbackAction::SelectDevice => {
            let device = &app.menu.device;
            for dev in device {
                let &(ref item, _) = dev;
                status.unsel_item(*item as u64);
            }
            status.sel_item(cmd.sender);
            // Spotify is broken.  Must be 'true', always starts playing.
            require(spotify.transfer(cmd.data.clone(), true));
        },
        CallbackAction::PlayPause => {
            let player_state = spotify.request_player_state();
            match player_state.is_playing {
                true => {require(spotify.pause());},
                false => {require(spotify.play(None));},
            }
            let play_str = play_action_label(!player_state.is_playing);
            status.update_item(app.menu.play, play_str);
        },
        CallbackAction::Preset => {
            play_uri(spotify, None, Some(&cmd.data));
        }
        CallbackAction::SkipNext => {
            require(spotify.next());
        }
        CallbackAction::SkipPrev => {
            require(spotify.previous());
        }
        CallbackAction::Volume => {
            let vol = cmd.data.parse::<u32>().unwrap();
            require(spotify.volume(vol));
            let volume = &app.menu.volume;
            for item in volume {
                status.unsel_item(*item as u64);
            }
            status.sel_item(cmd.sender);
        }
    }
}

fn refresh_time(app: &mut ConnectrApp, now: i64) -> i64 {
    let refresh_offset = match app.player_state.as_ref() {
        Some(ref state) => {
            match state.is_playing {
                true => {
                    let track_end = match state.progress_ms {
                        Some(prog) => {
                            if prog < state.item.duration_ms {
                                state.item.duration_ms - prog
                            }
                            else {
                                0
                            }
                        },
                        None => state.item.duration_ms,
                    } as i64;
                    // Refresh 1 second after track ends
                    track_end/1000 + 1
                },
                false => REFRESH_PERIOD,
            }
        }
        None => REFRESH_PERIOD,
    };
    let refresh_offset = std::cmp::min(REFRESH_PERIOD, refresh_offset) as i64;
    println!("State refresh in {} seconds.", refresh_offset);
    now + refresh_offset
}

fn main() {
    create_logger();
    info!("Started Connectr");

    let mut app = ConnectrApp {
        menu: MenuItems {
            device: Vec::<(MenuItem, String)>::new(),
            play: ptr::null_mut(),
            next: ptr::null_mut(),
            prev: ptr::null_mut(),
            preset: Vec::<MenuItem>::new(),
            volume: Vec::<MenuItem>::new(),
        },
        device_list: None,
        player_state: None,
    };
    let mut refresh_time_utc = 0;
    let (tx,rx) = channel::<String>();
    let mut spotify = connectr::SpotifyConnectr::new();
    info!("Created Spotify controller.");
    spotify.connect();
    info!("Created Spotify connection.");
    spotify.set_target_device(None);
    #[cfg(target_os = "macos")]
    let mut status = osx::OSXStatusBar::new(tx);
    info!("Created status bar.");
    #[cfg(not(target_os = "macos"))]
    let mut status = connectr::DummyStatusBar::new(tx);

    loop {
        let now = time::now_utc().to_timespec().sec as i64;
        if now > refresh_time_utc {
            // Redraw the whole menu once every 60 seconds, or sooner if a
            // command is processed later.
            clear_menu(&mut app, &mut spotify, &mut status);
            fill_menu(&mut app, &mut spotify, &mut status);
            refresh_time_utc = refresh_time(&mut app, now);
            info!("Refreshed Spotify state.");
        }

        spotify.await_once(false);
        if let Ok(s) = rx.try_recv() {
            println!("Received {}", s);
            let cmd: MenuCallbackCommand = json::decode(&s).unwrap();
            handle_callback(&mut app, &mut spotify, &mut status, &cmd);
            refresh_time_utc = now + 1;
        }
        status.run(false);
        sleep(Duration::from_millis(10));
    }
}

fn require(response: SpotifyResponse) {
    match response.code.unwrap() {
        200 ... 299 => (),
        _ => panic!("{}", response)
    }
    println!("Response: {}", response.code.unwrap());
}

fn play_uri(spotify: &mut connectr::SpotifyConnectr, device: Option<&str>, uri: Option<&str>) {
    match device {
        Some(dev) => { spotify.set_target_device(Some(dev.to_string())); },
        None => { spotify.set_target_device(None); },
    }
    match uri {
        Some(s) => {
            let ctx = connectr::PlayContext::new()
                .context_uri(s)
                .offset_position(0)
                .build();
            require(spotify.play(Some(&ctx)));
        }
        None => {
            println!("Transfer!");
            require(spotify.play(None));
        }
    };
}
<|endoftext|>


<commit_before>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Testing/Sample app using the cuckoo_miner lib
//!

extern crate cuckoo_miner;
extern crate cuckoo_config;
extern crate env_logger;

use cuckoo_config::*;
use cuckoo_miner::CuckooMiner;

fn main() {

    let test_header = [0xA6, 0xC1, 0x64, 0x43, 0xFC, 0x82, 0x25, 0x0B,
                       0x49, 0xC7, 0xFA, 0xA3, 0x87, 0x6E, 0x7A, 0xB8,
                       0x9B, 0xA6, 0x87, 0x91, 0x8C, 0xB0, 0x0C, 0x4C,
                       0x10, 0xD6, 0x62, 0x5E, 0x3A, 0x2E, 0x7B, 0xCC];
    env_logger::init();

    let mut config = CuckooMinerConfig::new();
    config.num_threads=1;
    let mut miner = CuckooMiner::new(config).unwrap();
    let caps = miner.get_available_plugins().unwrap();

    //Let's just run through them all and mine the same thing
    for c in &caps {
        println!("Test finding solution on plugin with caps: [{}]", c);

        miner.init(c).expect("Miner initialisation failed.");
        let mut solution = CuckooMinerSolution::new();

        /*let result = miner.mine(&test_header, &mut solution).unwrap();

        if result == true {
           println!("Solution found: {}", solution);
        } else {
           println!("No Solution found");
        }*/
    }

    //Just a testing stub for the time being
    //let result=miner.mine(&test_header, &mut solution).unwrap();

    /*if result == true {
        println!("Solution found: {}", solution);
    }*/

}
<commit_msg>Few memory fixes to miner, test should run now.<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Testing/Sample app using the cuckoo_miner lib
//!

extern crate cuckoo_miner;
extern crate cuckoo_config;
extern crate env_logger;

use cuckoo_config::*;
use cuckoo_miner::CuckooMiner;

fn main() {

    let test_header = [0xA6, 0xC1, 0x64, 0x43, 0xFC, 0x82, 0x25, 0x0B,
                       0x49, 0xC7, 0xFA, 0xA3, 0x87, 0x6E, 0x7A, 0xB8,
                       0x9B, 0xA6, 0x87, 0x91, 0x8C, 0xB0, 0x0C, 0x4C,
                       0x10, 0xD6, 0x62, 0x5E, 0x3A, 0x2E, 0x7B, 0xCC];
    env_logger::init();

    let mut config = CuckooMinerConfig::new();
    config.num_threads=4;
    let mut miner = CuckooMiner::new(config).unwrap();
    let caps = miner.get_available_plugins().unwrap();

    //Let's just run through them all and mine the same thing
    for c in &caps {
        println!("Test finding solution on plugin with caps: [{}]", c);

        miner.init(c).expect("Miner initialisation failed.");
        let mut solution = CuckooMinerSolution::new();

        let result = miner.mine(&test_header, &mut solution).unwrap();

        if result == true {
           println!("Solution found: {}", solution);
        } else {
           println!("No Solution found");
        }
    }

    //Just a testing stub for the time being
    //let result=miner.mine(&test_header, &mut solution).unwrap();

    /*if result == true {
        println!("Solution found: {}", solution);
    }*/

}
<|endoftext|>


<commit_before>use std::io;

#[macro_use]
extern crate log;
extern crate syn;
extern crate clap;

use clap::{Arg, App};

mod logging;
mod bindgen;

use bindgen::Config;

fn main() {
    let matches = App::new("cbindgen")
                    .version(bindgen::VERSION)
                    .about("Generate C bindings for a Rust library")
                    .arg(Arg::with_name("config")
                         .short("c")
                         .long("config")
                         .value_name("CONFIG")
                         .help("the config to use. currently either `wr`, or `default`"))
                    .arg(Arg::with_name("v")
                         .short("v")
                         .help("whether to print verbose logs"))
                    .arg(Arg::with_name("INPUT")
                         .help("the crate or source file to generate bindings for")
                         .required(true)
                         .index(1))
                    .arg(Arg::with_name("OUTPUT")
                         .help("the path to output the directories to")
                         .required(false)
                         .index(2))
                    .get_matches();

    if matches.is_present("v") {
        logging::InfoLogger::init().unwrap();
    } else {
        logging::WarnLogger::init().unwrap();
    }

    let input = matches.value_of("INPUT").unwrap();
    let config = match matches.value_of("config") {
        Some(c) => Config::load(c).expect("unknown config"),
        None => Config::default(),
    };

    let lib = bindgen::Library::load(input, &config);

    let built = lib.build(&config).unwrap();

    match matches.value_of("OUTPUT") {
        Some(file) => {
            built.write_to_file(&config, file);
        }
        _ => {
            built.write(&config, &mut io::stdout());
        }
    }
}
<commit_msg>Simplify main<commit_after>use std::io;

#[macro_use]
extern crate log;
extern crate syn;
extern crate clap;

use clap::{Arg, App};

mod logging;
mod bindgen;

use bindgen::{Config, Library};

fn main() {
    let matches = App::new("cbindgen")
                    .version(bindgen::VERSION)
                    .about("Generate C bindings for a Rust library")
                    .arg(Arg::with_name("config")
                         .short("c")
                         .long("config")
                         .value_name("CONFIG")
                         .help("the config to use. currently either `wr`, or `default`"))
                    .arg(Arg::with_name("v")
                         .short("v")
                         .help("whether to print verbose logs"))
                    .arg(Arg::with_name("INPUT")
                         .help("the crate or source file to generate bindings for")
                         .required(true)
                         .index(1))
                    .arg(Arg::with_name("OUTPUT")
                         .help("the path to output the directories to")
                         .required(false)
                         .index(2))
                    .get_matches();

    if matches.is_present("v") {
        logging::InfoLogger::init().unwrap();
    } else {
        logging::WarnLogger::init().unwrap();
    }

    let input = matches.value_of("INPUT").unwrap();

    let config = match matches.value_of("config") {
        Some(c) => Config::load(c).expect("unknown config"),
        None => Config::default(),
    };

    let built = match Library::load(input, &config).build(&config) {
        Ok(x) => x,
        Err(msg) => {
            error!("{}", msg);
            error!("could not build bindings for {}", input);
            return;
        },
    };

    match matches.value_of("OUTPUT") {
        Some(file) => {
            built.write_to_file(&config, file);
        }
        _ => {
            built.write(&config, &mut io::stdout());
        }
    }
}
<|endoftext|>


<commit_before>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate clap;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use chrono::*;
use clap::{Arg, ArgGroup, App};
use error::WorklogError;
use std::env;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use timeclock::Direction;
use timeclock::now;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

// TODO This belongs in a config file somewhere
const WEEKSTART: i64 = Weekday::Sat as i64;

fn print_csv_entries<R: Read>(file: R) -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    for rec in csv_entries {
        println!("{}", rec);
    }
    Ok(())
}

fn print_full_summary<R: Read>(file: R,
                               rounding: util::Rounding)
                               -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        let hours = util::round(rec.seconds(), rounding) / 3600.0;
        total_hours += hours;
        println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

fn print_short_summary<R: Read>(file: R,
                                start_date: Date<FixedOffset>,
                                end_date: Date<FixedOffset>,
                                rounding: util::Rounding)
                                -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        if start_date <= rec.date() && rec.date() <= end_date {
            let hours = util::round(rec.seconds(), rounding) / 3600.0;
            total_hours += hours;
            println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
        }
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    Ok(data_path)
}

fn main0() -> Result<(), WorklogError> {
    // Using std env macro rather than depending on clap's. No difference
    // as far as I can tell.
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::from_usage("[in] -i, --in 'Record an In entry'"))
        .arg(Arg::from_usage("[out] -o, --out 'Record an Out entry'"))
        .arg(Arg::from_usage("[time] -t, --time <TIME> 'time'")
            .requires("inout"))
        .arg(Arg::from_usage("[memo] -m, --memo <MEMO> 'Memo for the entry'")
            .requires("inout"))
        .arg(Arg::from_usage("[summary] -s, --summary 'Print a summary'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[log] -l, --log 'Print the full log'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[round] -r, --round 'Round totals up to the next quarter hour'")
            .conflicts_with("inout"))
        .group(ArgGroup::with_name("inout").args(&["in", "out"]))
        .get_matches();

    let csv_path = try!(get_csv_path());

    let mut csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    let rounding = {
        if matches.is_present("round") {
            // round up in 15min intervals
            util::Rounding::Up(900.0)
        } else {
            util::Rounding::None
        }
    };

    if matches.is_present("in") || matches.is_present("out") {
        let dir = if matches.is_present("in") {
            Direction::In
        } else {
            Direction::Out
        };

        let time = matches.value_of("time").unwrap_or("now");
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.value_of("memo").unwrap_or("").to_owned();
        timeclock::mark_time(dir, time, memo, &mut csv_file);

        println!("Clocked {:#} at {}", dir, time.format("%F %I:%M %P"));

    } else if matches.is_present("summary") {
        try!(print_full_summary(&csv_file, rounding));

    } else if matches.is_present("log") {
        try!(print_csv_entries(&csv_file));

    } else {
        let today = now().date();
        let weekday = today.weekday() as i64;
        let days_back = (7 - WEEKSTART + weekday) % 7;
        let start_date = today - Duration::days(days_back);
        try!(print_short_summary(&csv_file, start_date, today, rounding));
    }

    Ok(())
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => {
            let _ = writeln!(&mut std::io::stderr(), "Error: {}", err);
        }
    };
}
<commit_msg>Inital support for displaying a range of dates<commit_after>// Worklog is for recording your hours.
//

extern crate chrono;
extern crate csv;
extern crate clap;
extern crate rustc_serialize;

mod error;
mod timeclock;
mod util;

use chrono::*;
use clap::{Arg, ArgGroup, App};
use error::WorklogError;
use std::env;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::PathBuf;
use timeclock::Direction;
use timeclock::now;

#[cfg(target_family = "unix")]
static CSV_FILE_NAME: &'static str = ".worklog.csv";
#[cfg(target_family = "windows")]
static CSV_FILE_NAME: &'static str = "worklog.csv";

// TODO This belongs in a config file somewhere
const WEEKSTART: i64 = Weekday::Sat as i64;

fn print_csv_entries<R: Read>(file: R) -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    for rec in csv_entries {
        println!("{}", rec);
    }
    Ok(())
}

fn print_full_summary<R: Read>(file: R,
                               rounding: util::Rounding)
                               -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        let hours = util::round(rec.seconds(), rounding) / 3600.0;
        total_hours += hours;
        println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

fn print_short_summary<R: Read>(file: R,
                                start_date: Date<FixedOffset>,
                                end_date: Date<FixedOffset>,
                                rounding: util::Rounding)
                                -> Result<(), WorklogError> {
    let csv_entries = try!(timeclock::read_timesheet(file));
    let records = timeclock::collect_date_records(csv_entries);

    let mut total_hours: f64 = 0.0;
    for rec in records {
        if start_date <= rec.date() && rec.date() <= end_date {
            let hours = util::round(rec.seconds(), rounding) / 3600.0;
            total_hours += hours;
            println!("{} {:.2} {}", rec.date().format("%F"), hours, rec.memo());
        }
    }

    println!("Total Hours: {:.2}", total_hours);
    Ok(())
}

/// Get the path for the csv data file
fn get_csv_path() -> Result<PathBuf, WorklogError> {
    let mut data_path = match env::home_dir() {
        Some(path) => path,
        None => {
            return Err(env::VarError::NotPresent).map_err(WorklogError::Env)
        }
    };

    data_path.push(CSV_FILE_NAME);
    Ok(data_path)
}

fn main0() -> Result<(), WorklogError> {
    // Using std env macro rather than depending on clap's. No difference
    // as far as I can tell.
    let matches = App::new(env!("CARGO_PKG_NAME"))
        .version(env!("CARGO_PKG_VERSION"))
        .author(env!("CARGO_PKG_AUTHORS"))
        .about(env!("CARGO_PKG_DESCRIPTION"))
        .arg(Arg::from_usage("[in] -i, --in 'Record an In entry'"))
        .arg(Arg::from_usage("[out] -o, --out 'Record an Out entry'"))
        .arg(Arg::from_usage("[time] -t, --time <TIME> 'time'")
            .requires("inout"))
        .arg(Arg::from_usage("[memo] -m, --memo <MEMO> 'Memo for the entry'")
            .requires("inout"))
        .arg(Arg::from_usage("[summary] -s, --summary 'Print a summary'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[log] -l, --log 'Print the full log'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[round] -r, --round 'Round totals up to the next quarter hour'")
            .conflicts_with("inout"))
        .arg(Arg::from_usage("[range] -R, --range <TIME> <TIME> 'range'"))
        .group(ArgGroup::with_name("inout").args(&["in", "out"]))
        .get_matches();

    let csv_path = try!(get_csv_path());

    let mut csv_file = try!(OpenOptions::new()
        .read(true)
        .write(true)
        .create(true)
        .open(csv_path));

    let rounding = {
        if matches.is_present("round") {
            // round up in 15min intervals
            util::Rounding::Up(900.0)
        } else {
            util::Rounding::None
        }
    };

    if matches.is_present("in") || matches.is_present("out") {
        let dir = if matches.is_present("in") {
            Direction::In
        } else {
            Direction::Out
        };

        let time = matches.value_of("time").unwrap_or("now");
        let time = try!(util::parse_multi_time_fmt(&time));

        let memo = matches.value_of("memo").unwrap_or("").to_owned();
        timeclock::mark_time(dir, time, memo, &mut csv_file);

        println!("Clocked {:#} at {}", dir, time.format("%F %I:%M %P"));

    } else if matches.is_present("summary") {
        try!(print_full_summary(&csv_file, rounding));

    } else if matches.is_present("log") {
        try!(print_csv_entries(&csv_file));

    } else if matches.is_present("range") {
        let range = matches.values_of("range").unwrap();//.collect();
        let range: Vec<DateTime<FixedOffset>> =
            try!(range.map(util::parse_multi_time_fmt).collect());
        try!(print_short_summary(&csv_file,
                                 range[0].date(),
                                 range[1].date(),
                                 rounding));

    } else {
        let today = now().date();
        let weekday = today.weekday() as i64;
        let days_back = (7 - WEEKSTART + weekday) % 7;
        let start_date = today - Duration::days(days_back);
        try!(print_short_summary(&csv_file, start_date, today, rounding));
    }

    Ok(())
}

fn main() {
    match main0() {
        Ok(_) => {}
        Err(err) => {
            let _ = writeln!(&mut std::io::stderr(), "Error: {}", err);
        }
    };
}
<|endoftext|>


<commit_before>#![feature(read_exact)]
#[macro_use]

extern crate capnp;
extern crate chrono;
#[cfg(feature = "coroutines")]
extern crate coio;
extern crate kafka;
extern crate log;
extern crate openssl;
extern crate rand;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate toml;

mod flowgger;
pub use flowgger::record_capnp;

const DEFAULT_CONFIG_FILE: &'static str = "flowgger.toml";
const FLOWGGER_VERSION_STRING: &'static str = "0.1.10";

fn main() {
    println!("Flowgger v{}", FLOWGGER_VERSION_STRING);
    let config_file = std::env::args().skip(1).next().unwrap_or(DEFAULT_CONFIG_FILE.to_owned());
    flowgger::start(&config_file);
}
<commit_msg>read_exact() is not behind a feature gate any more in -beta<commit_after>#[macro_use]

extern crate capnp;
extern crate chrono;
#[cfg(feature = "coroutines")]
extern crate coio;
extern crate kafka;
extern crate log;
extern crate openssl;
extern crate rand;
extern crate redis;
extern crate serde;
extern crate serde_json;
extern crate toml;

mod flowgger;
pub use flowgger::record_capnp;

const DEFAULT_CONFIG_FILE: &'static str = "flowgger.toml";
const FLOWGGER_VERSION_STRING: &'static str = "0.1.10";

fn main() {
    println!("Flowgger v{}", FLOWGGER_VERSION_STRING);
    let config_file = std::env::args().skip(1).next().unwrap_or(DEFAULT_CONFIG_FILE.to_owned());
    flowgger::start(&config_file);
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate helianto;
extern crate stdio_logger;
#[macro_use]
extern crate log;

use std::{env, fs, process};
use std::path::PathBuf;
use getopts::Options;
use std::path::Path;
use log::{LogLevelFilter};

use helianto::{Compiler, Settings};

const SETTINGS_FILE: &'static str = "helianto.toml";

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("s", "settings", "FILE", "use an alternate config file");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");
    opts.optflag("q", "quiet", "only display error messages");

    if ! cfg!(ndebug) {
        opts.optflag("D", "debug", "display debug information");
    }

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {
            m
        }
        Err(f) => {
            panic!(f.to_string())
        }
    };

    if matches.opt_present("help") {
        print_usage(&program, opts);
        return;
    }

    if matches.free.len() > 2 {
        error!("Invalid number of arguments");
        return process::exit(1);
    }

    let source_dir = if matches.free.len() > 0 {
        Some(PathBuf::from(matches.free[0].clone()))
    } else {
        None
    };

    let output_dir = if matches.free.len() > 1 {
        Some(PathBuf::from(matches.free[1].clone()))
    } else {
        None
    };

    stdio_logger::init(
        if matches.opt_present("quiet") {
            LogLevelFilter::Error
        } else if matches.opt_present("debug") {
            LogLevelFilter::Trace
        } else {
            LogLevelFilter::Info
        }
    ).expect("Could not initialize logging");

    let settings_file = matches.opt_str("settings").map(PathBuf::from);

    let mut settings = match read_settings(source_dir.as_ref(), settings_file.as_ref()) {
        Ok(s) => s,
        Err(e) => panic!("{}", e),
    };

    if let Some(path) = source_dir {
        settings.source_dir = path;
    }

    if let Some(path) = output_dir {
        settings.output_dir = path;
    }

    Compiler::new(&settings).run().unwrap_or_else(|err| {
        error!("Compilation failed: {}", err);
        return process::exit(2);
    });
}

fn read_settings<P: AsRef<Path>>(cwd: Option<&P>,
                                 settings_file: Option<&P>)
                                 -> helianto::Result<Settings> {
    if let Some(ref path) = settings_file {
        info!("Loading settings from {}.", path.as_ref().display());
        return Settings::from_file(path);
    }
    let settings_file = cwd.map(|p| PathBuf::from(p.as_ref()))
                           .unwrap_or(PathBuf::from("."))
                           .join(SETTINGS_FILE);
    if is_file(&settings_file) {
        info!("Loading settings from {}.", settings_file.display());
        Settings::from_file(&settings_file)
    } else {
        Ok(Settings::default())
    }
}

fn is_file(path: &Path) -> bool {
    fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
}
<commit_msg>The --init option works<commit_after>extern crate getopts;
extern crate helianto;
extern crate stdio_logger;
#[macro_use]
extern crate log;

use std::{env, fs, process, io};
use std::path::PathBuf;
use getopts::Options;
use std::path::Path;
use std::io::Write;
use log::{LogLevelFilter};

use helianto::{Error, Result, Compiler, Settings};

const SETTINGS_FILE: &'static str = "helianto.toml";

const DEFAULT_FILES: &'static [(&'static str, &'static [u8])] = &[
    ("css/normalize.css",      include_bytes!["../example_data/css/normalize.css"] as &'static [u8]),
    ("css/skeleton.css",       include_bytes!["../example_data/css/skeleton.css"]),
    ("css/custom.css",         include_bytes!["../example_data/css/custom.css"]),
    ("_layouts/head.html.hbs", include_bytes!["templates/head.html.hbs"]),
    ("_layouts/foot.html.hbs", include_bytes!["templates/foot.html.hbs"]),
    ("_layouts/page.html.hbs", include_bytes!["templates/page.html.hbs"]),
    ("welcome.markdown",       include_bytes!["../example_data/example.markdown"]),
];

fn print_usage(program: &str, opts: Options) {
    let brief = format!("Usage: {} FILE [options]", program);
    print!("{}", opts.usage(&brief));
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();

    let mut opts = Options::new();
    opts.optopt("s", "settings", "FILE", "use an alternate config file");
    opts.optflag("i", "init", "populate the source directory with default content");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");
    opts.optflag("q", "quiet", "only display error messages");

    if ! cfg!(ndebug) {
        opts.optflag("D", "debug", "display debug information");
    }

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => {
            m
        }
        Err(f) => {
            writeln!(&mut io::stderr(), "{}", f.to_string());
            return process::exit(1);
        }
    };

    if matches.opt_present("help") {
        print_usage(&program, opts);
        return;
    }

    if matches.free.len() > 2 || (matches.opt_present("init") && matches.free.len() > 1) {
        error!("Invalid number of arguments");
        return process::exit(1);
    }

    let source_dir = if matches.free.len() > 0 {
        Some(PathBuf::from(matches.free[0].clone()))
    } else {
        None
    };

    let output_dir = if matches.free.len() > 1 {
        Some(PathBuf::from(matches.free[1].clone()))
    } else {
        None
    };

    stdio_logger::init(
        if matches.opt_present("quiet") {
            LogLevelFilter::Error
        } else if matches.opt_present("debug") {
            LogLevelFilter::Trace
        } else {
            LogLevelFilter::Info
        }
    ).expect("Could not initialize logging");

    let settings_file = matches.opt_str("settings").map(PathBuf::from);

    let mut settings = match read_settings(source_dir.as_ref(), settings_file.as_ref()) {
        Ok(s) => s,
        Err(e) => panic!("{}", e),
    };

    if let Some(ref path) = source_dir {
        settings.source_dir = path.clone();
    }

    if let Some(ref path) = output_dir {
        settings.output_dir = path.clone();
    }

    if matches.opt_present("init") {
        if matches.opt_present("settings") {
            error!("Option \"--settings\" can't be used with \"--init\".");
            return process::exit(1);
        }
        return init_content(source_dir.as_ref());
    }

    Compiler::new(&settings).run().unwrap_or_else(|err| {
        error!("Compilation failed: {}", err);
        return process::exit(2);
    });
}

fn read_settings<P: AsRef<Path>>(cwd: Option<&P>,
                                 settings_file: Option<&P>)
                                 -> helianto::Result<Settings> {
    if let Some(ref path) = settings_file {
        info!("Loading settings from {}.", path.as_ref().display());
        return Settings::from_file(path);
    }
    let settings_file = cwd.map(|p| PathBuf::from(p.as_ref()))
                           .unwrap_or(PathBuf::from("."))
                           .join(SETTINGS_FILE);
    if is_file(&settings_file) {
        info!("Loading settings from {}.", settings_file.display());
        Settings::from_file(&settings_file)
    } else {
        Ok(Settings::default())
    }
}

fn init_content<P: AsRef<Path>>(source_dir: Option<&P>) -> ! {
    let source_dir: PathBuf = if let Some(path) = source_dir {
        path.as_ref().into()
    } else {
        PathBuf::from(".")
    };
    let settings_file = source_dir.join(SETTINGS_FILE);

    match unpack_files(DEFAULT_FILES, &source_dir) {
        Ok(_) => process::exit(0),
        Err(e) => {
            error!("{}", e);
            process::exit(2);
        }
    }
}

fn unpack_files<P: AsRef<Path>>(files: &[(&str, &[u8])], dest: &P) -> Result<()> {
    let dest: &Path = dest.as_ref();
    if files.len() == 0 {
        Ok(())
    } else {
        let current_file = files[0];
        let dest_file = dest.join(current_file.0);
        let parent_dir = try! {
            dest_file.parent().ok_or(Error::Settings {
                message: format!("\"{}\" is not a valid directory", dest.display()),
            })
        };

        debug!("Creating directory {} …", parent_dir.display());
        try! { fs::create_dir_all(&parent_dir) }

        info!("Creating {} …", current_file.0);
        let mut fh = try! { fs::File::create(&dest_file) };
        try! { fh.write(current_file.1).map(void) }

        unpack_files(&files[1..], &dest)
    }
}

fn is_file(path: &Path) -> bool {
    fs::metadata(path).map(|m| m.is_file()).unwrap_or(false)
}

#[inline]
fn void<T: 'static>(_arg: T) -> () {
    ()
}
<|endoftext|>