Tuesday, September 14, 2010

Sunday, July 18, 2010

Recording both sides of a Skype convo (OS X)

Cracked it, without Audio Hijack. 1. Install SoundFlower. 2. In Audio/MIDI Setup, create an aggregate device (the "+" button) containing SoundFlower and your input device. 3. Launch Soundflowerbed, select your main output under "Soundflower (2ch)". 4. Set Skype to output to Soundflower (2ch) (leave the input as-is). 5. In Logic/Live/GarageBand, set the input to the aggregate device. Create 2 stereo channels, and make a test call.

Now that I knew what to look for, I found that someone already figured this out.

This should also work for Google Talk or Gizmo5 or any other VoIP app where you can set the audio output. In fact, if you set your default audio output in Audio/MIDI Setup to Soundflower, that should make everything else just work.

Monday, June 1, 2009

Verizon Family and Friends: By the Numbers

You could guess what your 10 most called are, or you could measure. Guess what I prefer. Find the "Download SpreadSheet" (sic) option on the Verizon site, and pipe it through some Python like this;

import csv, operator
calls = list(csv.DictReader(open('/home/kcarnold/Desktop/VoiceDetails.action'),
delimiter='\t'))
not_in = [c for c in calls if 'M2MAllow' not in c['Usage Type']]
minutes = {}
for call in not_in:
   number, mins = call['Number'], int(call['Minutes'])
   minutes.setdefault(number, 0)
   minutes[number] += mins
sorted(minutes.items(), key=operator.itemgetter(1))

Wednesday, December 10, 2008

Jesus is Precious

The apostle Peter says, "To you who believe . . . [he] is precious" (1 Peter 2:7). The grace of God makes Christ precious to us, so that our possessions, our money, our time [and our abilities -ken] have all become eternally and utterly expendable. They used to be crucial to our happiness. They are not so now.
 Tim Keller, Ministries of Mercy, page 63 (The Motivation for Mercy: Grace and Generosity)

Sunday, November 2, 2008

Sword Project Bible Reader in Python updated

I've updated and finished the core functionality for a pure Python reader for SWORD Bible modules (hosted on github). I had previously posted an initial proof-of-concept, and now figured out how to map references to keys.

Still to do: OSIS rendering, abbreviation processing, and the sort of convenience stuff that a frontend would want (Next/Previous, etc.).

Friday, August 8, 2008

Supremacy of Christ

I want today to commend to each one of us the supremacy of Jesus Christ and his Gospel. It is both the supreme glory of God and the solid rock for our lives. These words don't do it justice. It's hard to find any words that do, but these by Piper do a lot better than mine:

http://www.youtube.com/watch?v=oYGLl0gO1dk&feature=related

We were made to know Christ, not do little trivial things.


I was also recently led to read a familiar passage a little differently. When I did, the emphasis lay on these words:

truth, righteousness, gospel of peace, faith, salvation, Word

They are of course the real things that comprise the "armor of God". I encourage you to likewise read Ephesians 6 with the supremacy of the Gospel in view.

One observation I took from that is that one way that the Cross breaks the enemy's power is by removing the allure of the things that he offers. When the enemy offered Jesus bread, he didn't want it because he had something better. If you're concerned about your health, the enemy can control you with something that promises health (like a meditation technique, in my parents' case). But if the Holy Spirit has given you a new heart that regards the love of God as better than life, the temptation of worldly health will have no power over you. In that way, the Gospel (truth, faith, salvation, God's word, etc.) is your armor.

Other observations about the Gospel? Comment away...

Wednesday, August 6, 2008

Sword Project Bible Reader in Python

Update: I've updated this and put in on GitHub.

The SWORD API is complex. I did at one point try the SWIG wrapper, but that was still quite difficult to get right.

Fortunately, as complicated as the code is, what it actually does turns out to be very simple. With the help of zverse.cpp, libtool gdb examples/cmdline/lookup, and the Holy Spirit, I came up with this simple Python file to read a verse given an index:

#!/usr/bin/env python

# * ztext format documentation
# I'll use Python's struct module's format strings.
# See http://docs.python.org/lib/module-struct.html
# Take the Old Testament (OT) for example. Three files:
#
# - ot.bzv: Maps verses to character ranges in compressed buffers.
# 10 bytes ('<IIH') for each verse in the Bible:
# - buffer_num (I): which compressed buffer the verse is located in
# - verse_start (I): the location in the uncompressed buffer where the verse begins
# - verse_len (H): length of the verse, in uncompressed characters
# These 10-byte records are densely packed, indexed by VerseKey 'Indicies' (docs later).
# So the record for the verse with index x starts at byte 10*x.
#
# - ot.bzs: Tells where the compressed buffers start and end.
# 12 bytes ('<III') for each compressed buffer:
# - offset (I): where the compressed buffer starts in the file
# - size (I): the length of the compressed data, in bytes
# - uc_size (I): the length of the uncompressed data, in bytes (unused)
# These 12-byte records are densely packed, indexed by buffer_num (see previous).
# So the record for compressed buffer buffer_num starts at byte 12*buffer_num.
#
# - ot.bzz: Contains the compressed text. Read 'size' bytes starting at 'offset'.
#
# NT is analogous.

# Configuration (set this to your own modules path):

modules_path = '/home/kcarnold/.sword/modules/texts/ztext'


import struct, zlib
from os.path import join as path_join

class ZModule(object):
def __init__(self, module):
self.module = module
self.files = {
'ot': self.get_files('ot'),
'nt': self.get_files('nt')
}

def get_files(self, testament):
'''Given a testament ('ot' or 'nt'), returns a tuple of files
(verse_to_buf, buf_to_loc, text)
'''
base = path_join(modules_path, self.module)
v2b_name, b2l_name, text_name = [path_join(base, '%s.bz%s' % (testament, code))
for code in ('v', 's', 'z')]
return [open(name, 'rb') for name in (v2b_name, b2l_name, text_name)]

def text(self, testament, index):
'''Get the text for a given index.'''
verse_to_buf, buf_to_loc, text = self.files[testament]

# Read the verse record.
verse_to_buf.seek(10*index)
buf_num, verse_start, verse_len = struct.unpack('<IIH', verse_to_buf.read(10))

uncompressed_text = self.uncompressed_text(testament, buf_num)
return uncompressed_text[verse_start:verse_start+verse_len]

def uncompressed_text(self, testament, buf_num):
verse_to_buf, buf_to_loc, text = self.files[testament]

# Determine where the compressed data starts and ends.
buf_to_loc.seek(buf_num*12)
offset, size, uc_size = struct.unpack('<III', buf_to_loc.read(12))

# Get the compressed data.
text.seek(offset)
compressed_data = text.read(size)
return zlib.decompress(compressed_data)

if __name__=='__main__':
import sys
mod_name = sys.argv[1]
testament = sys.argv[2]
index = int(sys.argv[3])

module = ZModule(mod_name)
print module.text(testament, index)

This was a one-evening project, mostly taken up by the reverse-engineering. As you can see, Python provides a lot of the foundation work so that the code we actually have to write is very small.

I still need to figure out how human-readable verse identifiers get mapped to those numerical indices. It's hidden somewhere in VerseKey...