Saturday, November 13, 2021

Unit curves for controller response

My controller, e.g. MIDI fader, has linear range normalized to [0, 1].

My software has a control normalized to [0, 1].

But when I map the controller to the control, it doesn't feel right. It isn't expressive, all the interesting result is in one part of the controller.

So I use some function to map [0, 1] to [0, 1] in a non-linear way. The following are some practical functions which are fairly simple and supported by most environments

sqrt(x) is fast in, linear out

x^2 ease in, linear out


of course sqrt(x) and x^2 are both from the general form y=x^t where t=1 is linear, values of 0.75 0.5 0.25 will make the start fast and faster, 1.5 2.0 4.0 will make the start slower and slower. 

arcsin seat

Fast in, fast out, gives more control over the middle. In the following formula, the 1.5 is a tuning factor for how extreme the seat is, a value of 0 gives a linear response, 2.7 is the practical maximum with a large flat spot in the center.

In DDMathParser and VDMX, this is 
((0.5+asin(2*($VAL-0.5))/pi())-$VAL) * 1.5+$VAL

tanh s-curve

Speeds through the middle, gives more control over the edges.

The formula is a bit kludgy to fit the tanh to the unit square, and give values slightly beyond the [0, 1] range at the edges. The 1 is a tuning factor, reduce to 0.8 or 0.5 to give a softer response. Increasing above 1.0 will result in bigger dead spaces at the ends where the result is outside the [0, 1] range.

haversin s-curve

Speeds through the middle, gives more control over the edges. 0 and 1 and 0.5 map perfectly.

The haversin is equivalent to (1-cos(x))/2. Multiply x by PI to fit it into [0, 1].

You can also find deviation from linear by subtracting X, tune the deviation and add back. Tuning factor below 1 will make the curve subtler, but you can't tune above 1 without exceeding the output range.



double exponential seat & s-curve

If your environment supports switching based on x value, then it is easy to combine two exponential functions for the left and right half, to make a seat or s-curve which is tunable to be very extreme. See here for more information.

notes


Graphs from Desmos.
Reference for math functions.
For more inspiration, see The Book of Shaders and resources linked from there.








Sunday, September 12, 2021

Cycle of fifths, not circle of fifths

 Western music has 12 semitones per octave. The strongest ratio, 3/2, is the 7th note above the starting point, out of the 12 notes that take you up to the octave (and thus back to your "starting point" because we consider it the same note). This interval is called the "perfect fifth".

Because 7 doesn't divide evenly into 12, going up 7, and up 7 from there, and up 7 from there (the fifth of the fifth of the fifth) will eventually visit all 12 notes in a scrambled order before returning to where you started. When doing this exercise, it is customary to drop down an octave whenever you get too high, because otherwise you'll go past the highest note your instrument can play.

This is a "cycle of fifths" and the way it interacts with other constructs such as the major scale, note names, and key signatures yields a number of interesting patterns.

However many people use the name "circle of fifths" which leads to endless infographics laid out in a circle. This is unfortunate because it makes it hard to compare between fifths and obscures some of the pleasing patterns that can emerge from seeing e.g. the order in which piano keys become sharped.

So strongly prefer to present information as a "cycle of fifths" in a grid where adjacent fifths can be easily compared.

Tuesday, December 22, 2020

Reaper clipping, limiting, and loudness for mastering.

 Reaper includes some tools for managing loudness and peaks. Let's look at them and what they do.

Background.

Mastering is the process of preparing completed songs for distribution. In particular, adjusting the overall EQ and managing the loudness and peaks. For digital distribution, you generally want to target a specific loudness such as -14 LUFS, and keep peaks at -1dB.

Hard clipping happens when the peaks of a loud signal are clamped. There is a sharp bend in the waveform which introduces aliasing and harsh distortion. For content such as sin waves, piano, and voice, this distortion will be very audible. For thick and dirty pop and rock, hard clipping might not be noticed or might yield a pleasing result.

Soft clipping is any method that squishes the peaks down as they approach / exceed the 0dB limit. Soft clipping avoids the sharp bend and harsh distortion of hard clipping, but does affect the sound. There might be some subtle harmonic distortion, or you might notice some of the sharpness of the mix is reduced.

When mastering, it is common that after using gain to achieve the desired loudness, there will be peaks above -1db that need to be clipped, using hard and/or soft clipping (among the many other methods in the DAW toolkit). Some of these plugins include controls for loudness (gain into the clipping) and peak ceiling (gain after clipping). These are generally the same as you would get by adding gain plugins before and after. The only thing that ultimately matters is the final output: is it loud enough, are the peaks less than -1db, and is it free of undesired audible artifacts.

Setup

Note at C3 into ReaSynth triangle wav at 0db into an oscilliscope. Shows mapping of input to output level.


Event Horizon Clipper

"Threshold" boosts gain and introduces hard clipping

"Ceiling" is just a volume duck applied after the hard clipping

"Soft Clip" is a buggy mess that introduces additional unnecessary discontinuities.

Never put this in your mastering chain!


Event Horizon Limiter/Clipper

"Threshold" boosts gain and introduces hard clipping where peaks hit 0db

"Ceiling" is a gain attenuation applied after the hard clipping

"Release" has no visible effect, even at relevant time scales

"Ceiling" by itself is just a gain attenuation. Moving "Threshold" down loudens at the expense of hard clipping. Hard clipping will be very audible on many types of content, and there are probably better ways to louden. Might be useful at "Threshold -1, Ceiling -1" as a last line of defense to guarantee no peaks above -1dB [common advice to avoid problems that digital music services might have when encoding a file that hits 0db]. But ideally you want to have your peaks under control before hitting this plugin... in which case you wouldn't need it at all. If you notice that the input meter recorded a peak above -1dB, then clipping happened somewhere, and would be audible on a sin wave. If you see an input peak of 6dB then this plugin probably introduced aliasing artifacts.


JS Soft Clipper / Limiter

Bends the tops of peaks so they don't stick as far up. Imposes a hardclipping limit on the output signal. Below -6dB the response is linear, so it will only impact the louder parts of the peaks.

"Boost" boosts gain going into the curve, increasing loudness, pushing peaks further into the bend, and possible introducing/increasing hard clipping.

"Output Brickwall" moves the hardclipping threshold down, without decreasing loudness. This makes the bend more extreme, and makes it more likely your peaks hit the hardclipping threshold. e.g. my peaks are perfectly 0dB, I pull the brickwall down to -1dB, now the top 1dB of my peaks are hardclipped.

With controls at 0, If the input peak is 0dB, the output peak will be bent down to -1.9dB giving you more headroom. If the input peak is 0dB, I can use Boost to add 4dB of fairly transparent loudness which brings the output peaks back up to 0dB again. At this point any further boost, or pulling down the brickwall, or higher input peaks will introduce hardclipping.

This plugin is a nice option because it allows some loudening before hardclipping. If the input peaks are not under control, hardclipping will be introduced.


JS ReaLoud

Implements a curve map which soft clips, guaranteeing output peaks never exceed 0db, and adds 3dB of loudness in the process. The curve is linear until around -3dB, so only the highest peaks are modified.

"Mix" fades the effect in. At 0% the signal is untouched, at 50% there will be 1.5dB of loudness added. Note that the 0dB clipping is always applied, and the lower the mix value the harder the clipping (the sharper the angle).

There is no free lunch; the bending of the curve on peaks will color the sound somewhat. And it kicks in pretty hard at -3dB (compared to the -6dB of the soft clipping part of JS Soft Clipper) But even though extreme peaks will end up completely flat (which is not a natural place for the speaker cone to sit), the curve bends smoothly into flat, so it doesn't introduce sharp aliasing artifacts the way that hardclipping does.

The 3dB of loudness gain is not only arbitrary but almost besides the point. This plugin gives you a nice soft clipping to tame your peaks. Put a -3dB gain in front of it, and you cancel out the loudness boost. If you need more loudness, add a linear gain in front of it and drive it do desired loudness.

There is also a version with a lowpass filter.

Recommended. Set mix to 100% to avoid hardclipping. Follow with a -1dB attenuation to avoid 0dB peaks in the output file. Put a pre-gain in front of it to adjust the desired loudness. Start with -3dB to avoid driving the curve. Measure the LUFs of the output file, and increase the pre-gain as much as necessary to hit -14LUFs. Always double-check with your ears.



JS Louderizer

"Mix" fades the effect in.

"Drive" adjusts the curve.

Mix with no Drive does nothing, including no clipping.

Drive with no Mix does nothing, including no clipping.

Drive 100% and slowly bring the mix in, it bends the curve.

Drive 100 Mix 100 looks the same as ReaLoad for inputs less than 0db, but overdriving it produces a negative response!

Strictly inferior to ReaLoud and rather useless for mastering.







Friday, June 26, 2020

Musical Time in After Effects (BPM, beat, phase, loop)

Musical Time in After Effects

Much of modern music is generated to a strict metronome, or on a grid in a music editor. So if we known the precise BPM and where the first beat is, we can predict the exact location of every beat in the song, and extrapolate counters for bars, loops, and cycles.

Editing keyframes to music by hand is time-consuming and error-prone. It is easy enough to create a phrase of keyframes and add a loopOut() script. However the keyframes and the looping are limited by the accuracy of a single frame, and a frame is pretty large in musical time. You might have found yourself having to choose between the frame just before or just after a sound happens, searching for the best alignment. Now imagine that amount of slack multiplied tens or hundreds as the frame rounding errors accumulate every loop. At 90 BPM and 30fps, each beat is 20 frames. Assume half a frame of rounding error for a one-beat loop (imagine something throbbing with a 4/4 kick drum) and after a few seconds it is visibly out of sync. You can move to larger 8- and 16-bar loops, but the drift will still be ruinous by the end of the song.

A solution to this is to calculate (or be told) the BPM to 4 or 5 significant digits (e.g. 98.265). In a music editor you can visually and audibly verify that every single beat of the song is accurately located by this BPM. Then use some scripting in After Effects to calculate everything in floating point from this very accurate BPM.

"Music BPM.ffx" is a preset that does some basic calculations to provide accurate musical beat and bar count and phase. You can then pick-whip these and use simple expressions to design musical movements. Because everything is calculated in floating point from your very accurate BPM, everything will stay perfectly in sync.

Using the preset

Get a very accurate BPM value, and if the beat doesn't start at 0:00 also a frame-accurate time value for where the beat drops. Put the audio file in your project at 0:00, add the "Music BPM" preset. You will get the following fields:
  • input_BPM: put your very accurate BPM here
  • input_Downbeat: put here where the beat drops, in seconds
  • input_BeatsPerBar: most music works well with 4, but 8 or 16 might be better defaults for some music, or you can put odd numbers here for odd time signatures
  • BeatCount: outputs a beat counter, which starts negative and counts "down" to 0 when the downbeat happens, then up from there. You can use this to mark different sections of the song, and to calculate different cycles and rhythms;
  • BeatPhase: ramps from 0 to 1 every beat
  • BarPhase: ramps from 0 to 1 every bar
  • BarBeats: ramps from e.g. 0 to 3 every bar. Sometimes easier to think about than pure phase.

Some recipes

Throb with the beat

Add a size expression to your target layer. Pick-whip the "BarPhase" slider, and edit the expression to the following. Use linear() to set the limits for the response, because
a) size is on a scale of 100 while phase is on scale of 1
b) it looks bad to go all the way to 0, pick tasteful endpoints
c) we want to map the beginning of the phase (0) to a larger scale.
In this case we need to convert a 1D value to 2D to control the size so we [s, s] at the end.

s = linear(thisComp.layer("song").effect("BeatPhase")("Slider"), 120, 100); [s, s]

Punchy Throb

"1 - phase" to get a ramp down from 1 to 0, then take it to the third power so that values less than 1 get pulled down quickly towards 0. Since we already have a ramp down, we don't need to swap the mix and max arguments to linear(). This gives us a curve that stays mostly near 100 with a strong punch to 120 on the beat. If instead we take pow(BeatPhase) and use linear(s, 120, 100), the curve would spend most of its time near 120, only falling off towards 100 right before the next beat hits. Two different vibes, each good in their own way.

s = Math.pow(1-thisComp.layer("song").effect("BeatPhase")("Slider"), 3);
s = linear(s, 100, 120);
[s, s]

alternate

s = Math.pow(thisComp.layer("song").effect("BeatPhase")("Slider"), 3);
s = linear(s, 120, 100);
[s, s]

Rotate once per bar

360 * thisComp.layer("song").effect("BarPhase")("Slider") 

Rock back and forth with the beat, smoothly

Use cos() so it starts at an extreme (sin will start centered) and -10 so it starts at the left.
-10 * Math.cos(2*Math.PI*thisComp.layer("song").effect("BarPhase")("Slider") )

Rock back and forth with the beat, jumping from left lean to right lean

Use the (condition ? true_value : false_value) ternary operator to pick one of two values. In this case sin() is a better fit for the timing we want.
-10 * (Math.sin(2*Math.PI*thisComp.layer("song").effect("BarPhase")("Slider") ) > 0 ? 1 : -1)

Change color with the beat

Modulate the BeatCount to within the range (0-4]. This ends up being the same as BarPhase, but for more complicated motions you will often end up working directly with BeatCount so that's what we do here. Use this number to cycle white-yellow-red-black at full opacity. I decided that I didn't want the colors to flash during the intro, so I added some logic to keep the color black until the beat dropped. For a more complicated song, I will use an expression controller named "HasBeat" and keyframe it on and off as the drums come in and out, so I can pick-whip it into expressions to disable them when there is no beat.

beatCount = thisComp.layer("song").effect("BeatCount")("Slider");
beatMod = (beatCount % 4 + 4) % 4;
c = [0, 0, 0, 1];
if (beatCount >= 0) {
  if        (beatMod < 1) { c = [1,1,1, 1]; }
  else if (beatMod < 2) { c = [1,1,0, 1]; }
  else if (beatMod < 3) { c = [1,0,0, 1]; }
}
c

Draw a custom keyframe curve, and have it repeat in perfect time

In this case the song had a 16-bar piano loop, and I wanted to respond to a few swells without the jitter of converting the audio directly to keyframes. I created an layer "Piano Curve" and made sure I had the piano loop lined up at 0:00 on the timeline. Looking at the waveform and listening to the loop, I keyframed the size to swell with the piano line. I then hid the "Piano Swell" layer, deleted the audio layer I had used as a guide, and put the following expression on my target layer.

loopBeats = 16;
loopSec = loopBeats * 60 / thisComp.layer("song").effect("input_BPM")("Slider");
downbeat = thisComp.layer("song").effect("input_Downbeat")("Slider");
loopedTime = ((time-downbeat) % loopSec + loopSec) % loopSec;
thisComp.layer("Piano Curve").transform.scale.valueAtTime(loopedTime)



Notes

% is remainder, and will go negative for negative numbers. For modulo, use (x % N + N) %N;

beatLen = 60 / bpm


Saturday, June 13, 2020

Modul8 / Modul8 Module Best Practices

Best Practices for Writing Modul8 Modules:

  • Variables are camelCase
  • Put all your code in Init(). Define functions like handleKeyword(keyword, param, layer) and the only code in the KeywordEvent() block should be to call your handleKeyword() function. Keeping all the code on one screen makes it easy to audit, rename variables, and understand what the code is doing. You can also use "return" to skip code, instead of indenting the rest of the method.
  • Add a "module active" toggle button which defaults to off and auto-serializes. If this button is off, your module does nothing. Modul8 does not save which modules are active on a per-project basis. So if users have a lot of different projects using different modules, it is a common problem that an old project won't work until they figure out which modules to turn on and off. Adding an active toggle to your module lets them save that information as part of the project and there is no need to actually turn off the modules at the modul8 level. This is especially important for modules that have periodical, direct event, or keyword actions, because those might screw up someone's project. But it is also nice for performance reasons, if your module does a lot of GUI updates, to be able to skip them when the module is turned off.
  • Use versions on your modules, and put a changelog in the description. You can use option-Enter to add newlines to the description box.
  • Use the names of GUI elements rather then the messages. Specifically, in MessageEvent() ignore 'msg' and use param['NAME'] instead. The names are easier to find in the GUI editor, and you have to use name when modifying the GUI from the code. Having different values for the message in the "Script Connect" area, or having to keep the messages and names in sync is bothersome and an easy source of bugs. You do have to put something in the "script connect" box, but as long as you ignore the 'msg' variable in your code it doesn't matter what it is.
  • Logging script output is very CPU-intensive, so comment out all your debug message when done. If your module outputs to console as part of its feature, then it should have a "module active" button that defaults to False
  • If your module will have a (global) and (layer) version, define a variable "global = False" and write your code to handle both modes. Anytime you update the code, copy it from the (layer) module into the (global) module and change the value to True. Alternately, copy the .m8m file on disk which will include the layout as well as the code. Then you only need to update the 'global' variable to True.
  • Consider ignoring GUI changes during startup. If you have a fader that drives some keywords, but might be out of sync because the user changed those keywords through the main modul8 GUI, then you should ignore the fader position on load. Otherwise, you will override the values in the stored project: "hey, why are these values different than I left them??". This is especially important if your module doesn't have an [active] button which defaults to off. Define "finishedInit = False" in Init() and then set it true in PeriodicalEvent(); empirically, MessageEvent of saved state will run before PeriodicalEvent, so if not finishedInit you know it is due to project load and not an explicit user interaction. Turning off auto-serialize for certain GUI elements is another way to address this, although you will then lose the information about that element's value at time of save.
Best Practices for Modul8:
  • Use LB Notes and write down how your projects are structured, which modules are being used, and which MIDI and keyboard bindings you use.

Tuesday, April 2, 2019

Setting up OSX for performance / public screening

Turn off menu bar on second display (System Preferences -> Mission Control -> uncheck "Displays have separate Spaces"; logout and log back in)

VLC preferences:
interface -> continue playback: never
video -> uncheck "show video in main window"
video -> fullscreen video device -> screen 2
subtitle/OSD -> turn off OSD
Save
Re-open preferences and go to advanced mode
Playlist -> uncheck "Auto Start"
Interfaces -> Main Interfaces -> macosx -> uncheck "Show Fullscreen Controller"
Save

Might require restarting VLC and re-checking the options a few times before it sticks. Should leave you with the playlist in your main window and completely clean video player fullscreen on second display.

System Preferences -> Desktop and Screensaver; find the window on the second display. Select a file containing all-black pixels (alternately, logo). Note: recently Apple has added a true black in the Colors section.

If any app is using the microphone, then you'll want to hide the orange dot on the second display. This is a great security feature, but rather than giving users a way to control it Apple is in an arms race to make it impossible to hide. Pre-12.2 see here, post-12.2 here, and it might be worth searching for the latest info to see if things have changed.

An additional technique I use for playlists when I need to hold the next film until the MC has finished, is to insert a highly compressed 1-hour black/silent file between every pair of films. I let the previous film run out and playback automatically moves onto the long black, and when it is time for the next film I tap the "next" button once. Compared to juggling stop / play / next there is less room for error, and no need to move my mouse pointer.

Thursday, June 14, 2018

Control Modul8 From Reaper

Modul8 is VJ software for the Mac. Reaper is a full-featured and inexpensive DAW (with an unrestricted free demo).

Modul8 has no timeline, Reaper has a decent one.

To control Modul8 via MIDI from other software, I recommend my modules "LB - Control From MIDI CC" and "LB - Media from MIDI Notes" (available in the public library). With these modules installed and activated, you get direct control over nearly all layer and global parameters, and the ability to set media in layers, without having to mess around with interactive MIDI bindings.

For Reaper, I have created two files which will label the MIDI notes and CCs in Reaper's MIDI editor according to the Modul8 functions they will control. Install these in ~/Library/Application\ Support/REAPER/MIDINoteNames/ and load them via File -> Custom Note Names if you are editing a MIDI object and don't see the Modul8 parameter names.



There is also a sample Reaper project with tracks set up for each of the 10 Modul8 layers, and one more for control of global params. All MIDI from these track is forced onto the appropriate channel, so that you don't have to worry about setting the MIDI channel of each bit of MIDI data; just focus on which CCs and what values you are sending. If you prefer, you could have a single track containing MIDI data for multiple channels.



Download the files from Reaper Modul8 Control.zip

For this to work, you need to set up Reaper to enable MIDI output to M8. For most people this will be

  1. Use OSX's Audio MIDI Setup, in the IAC Driver, create a MIDI port called "Reaper to M8"
  2. Select "Reaper to M8" as a MIDI input in M8
  3. Enable "Reaper to M8" for output in Reaper's preferences
  4. In the Reaper project, adjust the routing for the topmost track and add MIDI hardware output to "Reaper to M8"
  5. In Modul8, double check that my modules are active
Play the timeline in Reaper, and see the Modul8 parameters respond.

Saturday, October 14, 2017

Modul8: "LB - Macro" module



Macro is an alternative to the "preset" concept.  Macro does not record the state of the modul8 parameters; rather, it records any number of changes to those parameters, and allows all those changes to be repeated by the press of a single button.




Modul8: LB Macro Module from Geoff Matters on Vimeo.


To start, turn on Learn for one of the macros, then take a few actions in modul8 such as toggling layer visibility, changing colorize and scale.  Turn off Learn.  Now, any time Play is pressed, it will return exactly those parameters modified, to the exact values they were when "learn" was turned off.  To test it, mess with the layer visibility / colorize / scale then press the Play button.  Note that unless a parameter was modified while Learn was on, it will not be adjusted when the macro is played back.  Note that the macro does not remember every intermediate value, only the most recent value for each parameter.  Note that some unwanted changes, such as layer focus, may be remembered as a side effect of a Macro eg if layer focus was changed during Learn.... this can interact with other parts of modul8.  Note that using another module during Learn does not record the use of the module, but records the actions the module takes.  For instance, if you use a random color module, the macro will not produce a random color each time but will always return to the color set during Learn.

Macros are a convenient way to bundle multiple predetermined actions into a single button, without having to write a module.  They are also useful to work around interface restrictions, eg use a Note On to enable something without the Note Off also disabling it (as it would with a direct MIDI mapping).

Version 1.0: store as dict rather than array
Version 0.8: use keywordsLB system, it can now learn keywords from other modules that also use the system

Note: "LB-Macro" (no spaces) was an early version of this uploaded 10 years ago. Obsolete, do not use.

Donate by Paypal

tinyloop: seamless video and audio looping for raspberry pi

Available at https://sites.google.com/view/tinyloop/

tinyloop

  • tinyloop is a raspberry pi image for video installations.
  • No need to log in; drag-and-drop video files onto the SD card itself, or onto an attached USB drive. Headless setup, plug-and-play.
  • Playback mode determined by the media content loaded:
    • Perfect seamless gapless endless looping of video with sound
    • Perfect seamless gapless endless looping of video
    • Looping playlist of multiple video files with sound (gaps between files)
    • Loop a single file (as gapless as omxplayer can manage)
    • Simple scripting, e.g. a short seamless video loop with a long gapless mix of audio files
  • Comes with sample content showing all playback modes.
  • Read-only system for reliability; no shutdown needed, simply unplug.
  • Tested on rpi zero and zero w, should run on earlier models.
  • Modern filesystem (NTFS, HFS+, ETX4) and large file support.
  • tiny; < 2GB, leaving plenty of space for media files. Power to video in 17 seconds.

Saturday, March 16, 2013

Creating cards to study English in Surusu


Dictionary word:


Search for the word in the dictionary. Copy the entire meaning and examples.

Back: full dictionary entry, e.g.

slop·py  (slp)
adj. slop·pi·er, slop·pi·est
1. Marked by a lack of neatness or order; untidy: a sloppy room.
2. Marked by a lack of care or precision; slipshod: sloppy use of language.


Front: dictionary entry with any obvious clues to the word removed, and the word replaced with ######## e.g.

######## 

1. Marked by a lack of neatness or order; untidy: a sloppy room.
2. Marked by a lack of care or precision; slipshod: sloppy use of language.



Using deck: dictionary

[Add Card]




Sentence


Front: a short sentence, e..g

How old do people usually think you are?

Back: leave empty

Using deck: Sentence

press the [+English] button

[Create Cloze Cards]


Optional: before hitting the [Create Close Cards] button, add a translation in your native language to the front of card



Long Cloze:


Front: Find a long text (several paragraphs) about a subject that interests you

Back: find one word you don't know from the text on the front. Look it up in the dictionary. Paste the full definition on the back. e.g.

1. hook up
1. recieved a good or service as a favor 
2. to make out with someone 
3. to have sex with someone

Using deck: longclose

Base Clozetexts: the word *as it appears in the text on the front of the card*, e.g.

hooked up

Cloze Mode: Manual mode

[Create cloze texts]

then repeat for 2-3 more words on front

Thursday, March 14, 2013

Hotkeys for Surusu

My biggest usability requirement for surusu is some decent hotkeys so I can do reps. The default accesskeys were designed for pre-smartphone cellphones, and are not ergonomic on a keyboard. My preferred layout is based around QWERTY right hand home row: K both shows the back of the card and scores it 3 (a reasonable default should you hit on accident or be unsure how to score) L and SEMICOLON score 4 and 5, and are used to push cards you know further off into the future. In the other direction, J scores a 1 when I forget a card. On the rare occasions when I barely miss, middle finger up to I scores a 2. I don't use 0.

Chrome:

UPDATED Oct 2014 for new 3-button layout (although if you look at surusu's code it seems insanely fragile and likely to break again next time the page changes). Install the Keyboard-fu add-on, go to its settings, Import/Export Hotkeys, and paste the following:



{"globalFilters":"[\"-https:#mail.google.com/*\",\"-https:#reader.google.com/*\",\"*\"]","hotkeys":"[[\"2\",\"k\",\"Show Back / Score 2/3\",\"if ($('#questionDiv').hasClass('repback')) {\\n  $('input[value=\\\"2 (>_<)...(~_~) 3\\\"]').click()\\n}  else {\\n  $('input[name=\\\"showanswer\\\"]').click()\\n}\\n\\n\\n\",[\"http://surusu.com/question.php\"]],[\"24\",\"l\",\"Score 4/5\",\"$('input[value=\\\"4 (^_^)...(^-^)/ 5\\\"]').click()\",[\"http://surusu.com/answer.php\"]],[\"25\",\";\",\"Score 4/5\",\"$('input[value=\\\"4 (^_^)...(^-^)/ 5\\\"]').click()\",[\"http://surusu.com/answer.php\"]],[\"27\",\"j\",\"Score 0/1\",\"$('input[value=\\\"0 (0_0)...(x_x) 1\\\"]').click()\",[\"http://surusu.com/answer.php\"]]]"}




Firefox:

Install “custom keyboard bindings” greasemonkey script (21947)

NOT UPDATED for single-page or new button layout. Edit the script and add this to the list of bindings:

"surusu.com":{
"question.php":{
  k:'//input[@name="showanswer"]'
},
"answer.php":{
  j:'//input[@accesskey="1"]',

i:'//input[@accesskey="2"]',
  k:'//input[@accesskey="3"]',
  l:'//input[@accesskey="4"]',
  SEMICOLON:'//input[@accesskey="5"]'
}
 },

Friday, February 22, 2013

EON NAS Expansion and upgrade

EON NAS has served me well for a few years, but I am out of space. Also considering to upgrade EON, and perhaps ZPOOL and ZFS versions (options such as block-level deduplication are appealing, as it makes it easy to bulk backup tons of old disks which are largely older versions of my current repo, without worrying about wasting space by having the same file many times)

First order of business: expand from 9x2TB to 9x4TB drives.  Following refs such as:

http://www.itsacon.net/computers/unix/growing-a-zfs-pool/

I first check that all my drives are currently alive, the system is fully silvered, and then scrub to make doubly sure there are no errors.

My pool is raidz2, so in theory I could replace two disks at once, but obviously that leaves me vulnerable. Having dual parity allows me to swap one disk at a time, and still be protected again a disk failure mid-upgrade!

Start with "zpool status", which shows mediapool totally healthy.

"zpool scrub mediapool"

Says it'll take 50 hours to complete. Well, we wouldn't have gone out of our way to use ZFS unless we were paranoid about our data, so we'll suck it up and wait it out.

Okay, scrub completed successfully. Shut down, remove one of the 2TB drives and replace it with a 4TB drive. Verify at boot that the BIOS sees the 4TB drive.


media:1:~#zpool status
  pool: mediapool
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://www.sun.com/msg/ZFS-8000-2Q
 scrub: none requested
config:

        NAME                    STATE     READ WRITE CKSUM
        mediapool               DEGRADED     0     0     0
          raidz2-0              DEGRADED     0     0     0
            c0t0d0              ONLINE       0     0     0
            c0t1d0              ONLINE       0     0     0
            c2t2d0              ONLINE       0     0     0
            c2t3d0              ONLINE       0     0     0
            c3t0d0              ONLINE       0     0     0
            c3t1d0              ONLINE       0     0     0
            c3t2d0              ONLINE       0     0     0
            c3t3d0              ONLINE       0     0     0
            390014080793031528  UNAVAIL      0     0     0  was /dev/dsk/c3t4d0s0

errors: No known data errors

#zpool replace mediapool c3t4d0s0
cannot open '/dev/dsk/c3t4d0s0': I/O error

cfgadm -s "select=type(disk)"
Ap_Id                          Type         Receptacle   Occupant     Condition
sata0/0::dsk/c3t0d0            disk         connected    configured   ok
sata0/1::dsk/c3t1d0            disk         connected    configured   ok
sata0/2::dsk/c3t2d0            disk         connected    configured   ok
sata0/3::dsk/c3t3d0            disk         connected    configured   ok
sata0/4::dsk/c3t4d0            disk         connected    configured   ok
sata1/0::dsk/c0t0d0            disk         connected    configured   ok
sata1/1::dsk/c0t1d0            disk         connected    configured   ok
sata2/2::dsk/c2t2d0            disk         connected    configured   ok
sata2/3::dsk/c2t3d0            disk         connected    configured   ok

So, the system sees c3t4d0. So then s0 does not exist probably. I can either replace with p0 to use the entire partition, or do a format to single slice and use s0. I don't recall why I used s0 before... probably so that I could upgrade some of the drives with larger ones with matching s0, then use s1 for extra space. Should be possible even with p0. Need to check my records.

Wait, that's not right. zpool replace should take a raw disk, format it, and resilver (according to http://docs.oracle.com/cd/E19082-01/817-2271/gbcet/index.html)

#zpool replace mediapool c3t4d0
cannot replace c3t4d0 with c3t4d0: device is too small

#format
Searching for disks...done


AVAILABLE DISK SELECTIONS:
       0. c0t0d0
          /pci@0,0/pci8086,3a46@1c,3/pci1458,b000@0/disk@0,0
       1. c0t1d0
          /pci@0,0/pci8086,3a46@1c,3/pci1458,b000@0/disk@1,0
       2. c1d0
          /pci@0,0/pci8086,244e@1e/pci-ide@0/ide@0/cmdk@0,0
       3. c2t2d0
          /pci@0,0/pci8086,244e@1e/pci1095,7124@1/disk@2,0
       4. c2t3d0
          /pci@0,0/pci8086,244e@1e/pci1095,7124@1/disk@3,0
       5. c3t0d0
          /pci@0,0/pci1458,b005@1f,2/disk@0,0
       6. c3t1d0
          /pci@0,0/pci1458,b005@1f,2/disk@1,0
       7. c3t2d0
          /pci@0,0/pci1458,b005@1f,2/disk@2,0
       8. c3t3d0
          /pci@0,0/pci1458,b005@1f,2/disk@3,0
       9. c3t4d0
          /pci@0,0/pci1458,b005@1f,2/disk@4,0

There's the problem; my drive, which shows up as 4000GB to BIOS, shows up as 1.64 TB within EON Solaris. Why? Poking around the net, it should be


It is an odd point that the perceived size is exactly 2TB less than the actual size. I'm running 64-bit solaris. The BIOS reports the drive as 4TB (need to double-check this is currently the case, as I tried a few different slots trying to get it to work)

Answer: although I was not able to find documentation of this, early versions of EON did not have support for 3TB+ drives completely in place. Need to update to recent version.

After updating to EON version 1.0b,


media:1:~#format
Searching for disks...done

AVAILABLE DISK SELECTIONS:
       0. c0t0d0
          /pci@0,0/pci8086,3a46@1c,3/pci1458,b000@0/disk@0,0

The drive's correct size is seen.

Check pool status


media:2:~#zpool status
  pool: mediapool
 state: DEGRADED
status: One or more devices could not be used because the label is missing or
        invalid.  Sufficient replicas exist for the pool to continue
        functioning in a degraded state.
action: Replace the device using 'zpool replace'.
   see: http://www.sun.com/msg/ZFS-8000-4J
  scan: none requested
config:

        NAME                      STATE     READ WRITE CKSUM
        mediapool                 DEGRADED     0     0     0
          raidz2-0                DEGRADED     0     0     0
            14963257236115845187  UNAVAIL      0     0     0  was /dev/dsk/c0t0d0s0
            c0t1d0                ONLINE       0     0     0
            c4t2d0                ONLINE       0     0     0
            c4t3d0                ONLINE       0     0     0
            c5t0d0                ONLINE       0     0     0
            c5t1d0                ONLINE       0     0     0
            c5t2d0                ONLINE       0     0     0
            c5t3d0                ONLINE       0     0     0
            c5t4d0                ONLINE       0     0     0

and we're ready to replace

media:4:~#zpool replace mediapool c0t0d0
cannot replace c0t0d0 with c0t0d0: devices have different sector alignment

Crap.

According to this thread it is completely impossible to reaplce a 512k-sector drive with a 4k-sector drive. Oddly, it seems that ZFS will actually tolerate some level of mixage between aligments (and sector size?) at time of pool creation, or adding drives to a pool, but not when it comes time to replace a drive. The *only* option appears to be to back all the data up and create a fresh pool. A very unappealing prospect. I also means I will need 7x2TB drives.

Although the above thread seems authoritative, need to sleep on it and understand the situation a little better before taking action.

I have enough 2TB drives to make a complete backup, but some of them are in use in other ways. I might have a few which are already backups from an older state of the EON pool. I can overwrite those with the current pool contents. After that I have some matched master / backup pairs of data which is queued to enter pool.

Also worth noting: at time of writing, the cheapest 4tb drives ($210) are the same value as 2TB drives ($105) but could be saved for spares in the new pool. So any new drives purchased should be 4TB.

...

After backing all media up to UFS-formatted drives, I created a new pool from the 9 4TB drives and coping all the files back. I failed to upgrade the pool in-place, but did end up with all my data safe and sound in the new system.

Thursday, February 21, 2013

Update EON from snv_125

According to andre, best is to fresh install. Failing that:

I have a working windows -> USB install but not yet ready for release. USB install/image coming ...

For now what you can do is

Insert 2nd key(new) and run install.sh. Install to new key.

After it is done you will have a clone of the first key.

Then, use transporter with the new iso to overwrite the 2nd key that you just installed/cloned.

Now you have the new image installed on the new key.

so, let's try that.

First, list all the drives:

media:5:~#echo | format -e
Searching for disks...done


AVAILABLE DISK SELECTIONS:
       0. c0t0d0
          /pci@0,0/pci8086,3a46@1c,3/pci1458,b000@0/disk@0,0
...
       9. c3t4d0
          /pci@0,0/pci1458,b005@1f,2/disk@4,0

then plug in the USB key and try again:

media:6:~#echo | format -e
Searching for disks...
The current rpm value 0 is invalid, adjusting it to 3600
done

c4t0d0: configured with capacity of 14.80GB

AVAILABLE DISK SELECTIONS:
       0. c0t0d0
          /pci@0,0/pci8086,3a46@1c,3/pci1458,b000@0/disk@0,0

      10. c4t0d0
          /pci@0,0/pci1458,5006@1a,7/storage@5/disk@0,0
Specify disk (enter its number): Specify disk (enter its number):

I can clearly see that the 16GB USB key is c4t0d0

media:7:~#install.sh
This process installs EON ZFS Storage to a destination listed below:
[1] c0t0d0 (Unknown MB)
[2] c0t1d0 (Unknown MB)
[3] c1d0 (3816MB)
[4] c2t2d0 (Unknown MB)
[5] c2t3d0 (Unknown MB)
[6] c3t0d0 (Unknown MB)
[7] c3t1d0 (Unknown MB)
[8] c3t2d0 (Unknown MB)
[9] c3t3d0 (Unknown MB)
[10] c3t4d0 (Unknown MB)
[11] c4t0d0 (Unknown MB)
Enter destination choice[?]: 11
 ... lots of stuff, have to answer 'y' a few times
/mnt/install/boot/x86.eon:       OK
EON ZFS Storage install complete on /dev/dsk/c4t0d0s0

rebooting... as before, my system hangs when a bootable solaris system is present on USB. It doesn't even finish listing all the PCI cards. So have to try again, targeting a second CF card.

media:4:~#install.sh
This process installs EON ZFS Storage to a destination listed below:
[1] c0t0d0 (Unknown MB)
[2] c0t1d0 (Unknown MB)
[3] c1d0 (3816MB)
[4] c1d1 (Unknown MB)
[5] c2t2d0 (Unknown MB)
[6] c2t3d0 (Unknown MB)
[7] c3t0d0 (Unknown MB)
[8] c3t1d0 (Unknown MB)
[9] c3t2d0 (Unknown MB)
[10] c3t3d0 (Unknown MB)
[11] c3t4d0 (Unknown MB)
Enter destination choice[?]: 4

After it succeeds, I shut down, remove the old boot system from slot 0 of the CF card, and move the newly created one from slot 1 to slot 0. It boots okay, I am able  to log in with my previously created account, and verify that the pool is healthy and ip addresses are correct. Looks like the new install worked. Now I have a playground to update, and the safety of the old system on the other CF card.

Now it is time to upgrade to the latest and greatest. For versions of EON slightly newer than mine, the upgrade tool is/was transporter.sh - see this post - and elsewhere in comments Andre advises those of us using older versions without transporter.sh to simply download the script from the downloads page.

I download transporter.sh and scp it into /tmp/ on my eon box.
Download the latest CIFS ISO and scp it into /tmp/ as well

Then as root on my eon box:

#chmod +x /tmp/transporter.sh
#/tmp/transporter.sh -i /tmp/eon-1.0b-151-64-cifs-min.iso -d /mnt/eon0
 OK: lofiadm -a /tmp/eon-1.0b-151-64-cifs-min.iso /dev/lofi/1
 OK: mount -F hsfs /dev/lofi/1 /tmp/upgrade
 removing /mnt/eon0/boot
 copying /tmp/upgrade -> /mnt/eon0
  ...
 unmounting /dev/lofi/1
 OK: umount /dev/lofi/1
 releasing /dev/lofi/1
 OK: lofiadm -d /dev/lofi/1

Great, complete with no problems. But we're not done quite yet. The new system just installed contains none of the setup I made to the original system - ip addresses, accounts, and other config. Normally we run updimg.sh to write changes we've made to the running system into the stored image so that they persist across a reboot. But in the comments here Andre cautions that by default, that script will overwrite parts of the new system with the old one. So according to his advice, edit /mnt/eon0/.backup and comment out the three entries in /usr/bin/ to avoid reverting them. Then

#updimg.sh /mnt/eon0/boot/x86.eon 
Updating files in /mnt/eon0/.backup to x86.eon
backup in /mnt/eon0/boot/x86.eon.1
 /mnt/eon0/.backup:     OK
gzcat /mnt/eon0/boot/x86.eon > /tmp/x86.1336
lofiadm -a /tmp/x86.1336 /dev/lofi/1
mounting ... /dev/lofi/1 /mnt/upd
 copying /etc/svc/repository.db
umounting ... /mnt/upd
lofiadm -d /dev/lofi/1
mv -f /mnt/eon0/boot/x86.eon /mnt/eon0/boot/x86.eon.oem
gzip -f -9 -c /tmp/x86.1336 > /mnt/eon0/boot/x86.eon
/mnt/eon0/boot/x86.eon:  OK

At this point we should be ready to reboot and enjoy our new system!

Rebooting, GRUB displays the new EON logo as well as the version number 0.97
Before the login prompt there are some errors related to the crypto service
I am not able to SSH in. I can log in using one of the accounts I previously created. zpool shows no pool. ifconfig -a shows that the ip address settings were also lost.

Unfortunate. I still have the disk with the original system, so I could go through the whole process again, but it is probably easier to move forward and fix the config.

first, 

#zpool import

resurrects my pool. Everything looks healthy, although "zpool status" notes that I am using an older version of on-disk format (meaning that there is now a new version available but I have yet to upgrade).

Actually, the docs on the eonstorage google site don't mention such pedestrian configs as network addresses. Referring to the notes from my original install... I also glossed over those bits.

ifconfig fails with an "Object not found" error

svcs -xv shows:

svc:/network/physical:default (physical network interfaces)
 State: maintenance since (time of boot)
Reason: Start method exited with $SMF_EXIT_ERR_CONFIG.
Impact: 21 dependent services are not running:
  nfs
  smb
  etc

svc:/network/physical:nwam (physical network interface autoconfiguration)
 State: disabled since (time of boot)
Reason: Disabled by an administrator
Impact: 21 dependent services are running

svc:/system/idmap/default (Native Identity Mapping Service)
State: maintenance since (time of boot)
Reason: Start method failed repeatedly, last exited with status 1
Impact: 5 dependent services
  smb
  nfs
  etc

svc:/system/cryptosvc:default (cryptographic services)
State: maintenance since (time of boot)
Reason: restarting too quickly
Impact: 2 dependent services
  ssh
  milestone


Okay, that's a bit of a mess, but it seems that if I could get the network working the rest might fall into place. ifconfig -a does show both of my cards, so they seem to be working at the hardware and driver level. What is the recommended way to configure stuff in EON?

Well, /etc/hostname.rge0 does contain the IP address that I had previously configured. Looking at /usr/bin/setup, I try to reproduce it... all the relevant files seem to have the correct info from previous setup. The only missing step is to start the net service:

#/lib/svc/method/net-physical
/lib/svc/method/net-physical[73]: /sbin/ibd_upgrade: not found [No such file or directory]
ifconfig: cannot plumb rge0: Interface already exists
ifconfig: cannot plumb rge1: Interface already exists
configuring IPv4 interfaces: ifconfig: could not create address:Object not found
 rge0ifconfig: could not create address:Object not found
 rge1
Failed to configure IPv4 interface(s): rge0 rge1

it is true that /sbin/ibd_upgrade does not exist. Googling only turns up two results for "/sbin/ibd_upgrade: not found" neither of which offers a clear explanation

Reboot again and transcribe onscreen errors:

WARNING: No major number for driver mega_sas in class scsi
WARNING: failed to resolve 'scsa.probe' driver alias, defaulting to 'nulldriver'
WARNING: no randomness provider enabled for /dev/random. Use cryptoadm(1M) to enable a provider
Configuring devices
Failed to configure IPv4 interface(s): rge0 rge1
svc.startd[8]: svc:/network/physical:default: Method "/lib/svc/method/net-physical" failed with exit status 96.
svc.startd[8]: network/physical:default misconfigured: transitioned to maintenance (see svcs -xv for details)
... may have missed some, output too fast for video recording to keep up with
svc.startd[8]: svc:/system/idmap:default: Method "/usr/lib/idmapd" failed with exit status 1
... cryposvc
... failed to abandon contract 37: Permission denied


Okay, put that aside for now and continue with setup: edit /mnt/eon0/.exec and enter correct pool name.
zpool import -> success
updimg.sh /mnt/eon0/boot/x86.eon
init 6 -> reboot

my zpool is still not imported on boot, even though .exec contains my correct pool name. "zpool import" in the command line succeeds. It seems that .exec is not being run? Or it is run, but "zpool import -f -a" fails because SMB etc services can't be started.

So 2 main issues: networking fails, zpool doesn't load on boot. Need to seek help, and read through blog comments for any similar troubleshooting.

Andre suggests I just start over, so backup my upgraded img and copy the OEM one to /mnt/eon0/boot/x86.eon

So now I'm following the "new setups" instructions from here


cd /mnt/eon0/bin
./slinky r
./slinky c
setup
check poolname in .exec
add group and user for media per my notes from original setup
updimg.sh
skip the nfs setup (I don't think I ever actually used it)
skip the permissions/owner/acl stuff for zfs and zpool - should be set correctly on disk from before, and I made sure to use same group and user IDs
reboot - zpool is online with no errors

okay i lied, I use NFS from my media server. Try to follow the instructions in the faq but the paths don't work anymore. Perhaps they moved, or perhaps they're part of binary kit now?

Found the answer in the forums:

"With the move to Illumos /var/svc/manifest/*.xml changed to /lib/svc/manifest/*.xml
Please redo the steps with /lib/svc/manifest"
Repeat the steps in under /lib/ and all the imports succeed, but:


#svcadm enable -r nfs/server
svcadm: svc:/milestone/network depends on svc:/network/physical, which has multiple instances.

nevertheless, despite the warning I am able to connect via NFS

For now, this seems to be complete and successful.

Saturday, December 1, 2012

Openelec on ASRock VisionX

Install

Installed openelec 3.0 beta 1 with two USB thumb drives - one primed with the installer, the other blank, plugged in after booting the installer, and installed onto.

Network

Setting up wifi (system -> openelec -> network) was fairly straightforward, the main pain point was that changing the options in the menu had no immediate effect. Once I realized that it is necessary to reboot after every change to network configuration things got sensible and was up and running with wifi (using device wlan0) in no time. SSH access: on first boot, after plugging in an ethernet cable, I was able to ping, ssh, and guess the username and password. However the settings for "run ssh server" weren't checked, so I checked "run ssh server" and "disable password authentication". However after doing this, any attempt to ssh in was met with "Permission denied (publickey,keyboard-interactive)." so I unchecked "disable password authentication" and after a reboot I was able to connect again.

Unicode

Next problem: lack of unicode. In 2012, anything that ships without support for international languages should be considered broken. Perhaps there is a reason for this situation (font licensing costs?) but it's a bit embarrassing at this point that it hasn't been sorted out. In fact, even people looking for support in the forums were coming up emptyhanded! The post at http://openelec.tv/forum/72-xbmc/27400-unicode-support gave me an idea of where to start.
root ~ # mkdir /storage/.xbmc/userdata/fonts root ~ # cp Arial\ Unicode.ttf /storage/.xbmc/userdata/fonts/arialuni.ttf root ~ # ls -l /storage/.xbmc/userdata/fonts/arialuni.ttf -rwxr-xr-x 1 root root 23278008 Nov 28 22:13 /storage/.xbmc/userdata/fonts/arialuni.ttf
Under the Confluence skin settings I changed Fonts to "Arial based". After this, unicode characters started to be displayed! I actually have no idea whether copying the old standby arial unicode was even necessary. It is a significantly larger filesize than the arial font included with openelec, so there is a good chance it includes more characters. It worked fine until I rebooted. After rebooting, all my labels were blank! I had to use screenshots from the xbmc wiki to navigate the text-free settings menus and change the font back to skin default! Cycling through the fonts, the default and no-caps-default both worked, but selecting "arial-based" causes the labels to go blank. Before reboot:
root ~ # ls -l /usr/share/xbmc/media/Fonts/// total 5048 -rw-r--r-- 1 root root 633604 Nov 25 15:09 DejaVuSans.ttf -rw-r--r-- 1 root root 123096 Nov 25 15:09 Trebuchet MS Bold.ttf -rw-r--r-- 1 root root 83980 Nov 25 15:09 YanoneKaffeesatz-Bold.ttf -rw-r--r-- 1 root root 4221580 Nov 25 15:09 arial.ttf -rw-r--r-- 1 root root 105344 Nov 25 15:09 teletext.ttf
After reboot:
root ~ # ls -l /usr/share/xbmc/media/Fonts/ total 22736 -rwxr-xr-x 1 root root 23278008 Nov 28 22:13 arialuni.ttf
It seems that the folder I created, /storage/.xbmc/userdata/fonts, was pulled into the readonly filesystem at reboot and overwrote the full collection of fonts! The missing fonts seem to be gone for good:
root ~ # find / | grep ttf /storage/Arial Unicode.ttf /storage/.xbmc/userdata/fonts/arialuni.ttf /usr/share/fonts/liberation/LiberationMono-Bold.ttf /usr/share/fonts/liberation/LiberationMono-BoldItalic.ttf /usr/share/fonts/liberation/LiberationMono-Italic.ttf /usr/share/fonts/liberation/LiberationMono-Regular.ttf /usr/share/fonts/liberation/LiberationSans-Bold.ttf /usr/share/fonts/liberation/LiberationSans-BoldItalic.ttf /usr/share/fonts/liberation/LiberationSans-Italic.ttf /usr/share/fonts/liberation/LiberationSans-Regular.ttf /usr/share/fonts/liberation/LiberationSerif-Bold.ttf /usr/share/fonts/liberation/LiberationSerif-BoldItalic.ttf /usr/share/fonts/liberation/LiberationSerif-Italic.ttf /usr/share/fonts/liberation/LiberationSerif-Regular.ttf /usr/share/xbmc/addons/skin.confluence/fonts/Roboto-Bold.ttf /usr/share/xbmc/addons/skin.confluence/fonts/Roboto-Regular.ttf /usr/share/xbmc/media/Fonts/arialuni.ttf
This also suggests that

  1. My previous attempt to install arialuni had no effect
  2. The arial font included has pretty good support for foreign characters, so for most users simply selecting "arial-based" as the skin font should be sufficient
  3. By naming any unicode font to arial.ttf we can cause it to overwrite the original and thereby use any font we desire
  4. Some things on openelec require a reboot, some don't, it is hard to know which is which, and if you are trouble-shooting you may be better off rebooting every step of the way to ensure you're actually observing the effects of any change you made.

So, one more try:
root ~ # mv /storage/.xbmc/userdata/fonts/arialuni.ttf /storage/.xbmc/userdata/fonts/arial.ttf
and reboot, Settings -> Appearance -> Skin -> Fonts -> Arial based

It works, after 2 seconds the menu redraws with Arial, and browsing my international content all the extended characters show up. The other fonts seem to be lost for good, but it hasn't hurt my experience yet. If you find the need to install a custom font, I would start by copying everything from /usr/share/xbmc/media/Fonts/ into /storage/.xbmc/userdata/fonts/ so that you don't lose any of them. Just in case they turn out to be useful someday.

Confirming that the old standby ultra-complete unicode font I added is being used:
root ~ # ls -l /usr/share/xbmc/media/Fonts/ total 22736 -rwxr-xr-x 1 root root 23278008 Nov 28 22:13 arial.ttf

Adding network shares

System -> File manager -> Add source -> Browse -> SMB -> browse for net shares, select desired folder, edit name, etc

However after the above, they still did not appear as media sources. So next up was

Videos -> Files -> Add videos... -> Browse -> as above

Attempting to set the media type, I opted to browse the available scrapers, and trying to cancel that I backed out (probably by ESC) and found that the folder had been added with whatever default settings it had. Adding NFS sources was similar, except that I had to type in the locations, e.g.

Add Video Source -> Browse -> Add network location... -> "nfs://10.0.1.50/mediapool/media"

after which it shows up as a source when I Browse, and I could browse within that hierarchy and select the folders I wanted to add with various names.

Audio

Audio didn't work. Actually, it did seem to work via the analog out that was set up by default, but I preferred to send it over HDMI.

Settings -> System -> Audio output -> Audio output -> HDMI Audio output device -> HDA ATI,
HDMI Passthrough output device -> HDA ATI, HDMI

Blu-ray images

System seems to have no problem playing e.g. 1080p mkv files, but playing blu-ray files results in about 2fps performance. All available hardware decoding options are checked. Software vs. hardware decoding yields same results.

http://forum.xbmc.org/showthread.php?tid=129509&page=2 - many people are reporting that choppy/slow blu-ray playback is due to the new audio engine in XBMC. According to their advice, selecting AC3 rather the HD audio did improve playback to mostly smooth with some painful slowdowns now and then. Still not at the point where I can actually watch a BD image, but getting closer.

At some point after trying out different settings even normal DVD were stuttering.

After upgrading to openelec 3.0 beta 2 and taking the advice at http://forum.xbmc.org/showthread.php?tid=145277&pid=1239524#pid1239524 to enable all advanced format options (WASAPI is not relevant so I left output HDMI) and check video settings, everything seems to play smoothly. It does sometimes pause for buffering, I assume this is due to the high bandwidth I'm trying to push over wifi and should go away if I switch to a cable.

TBD

Doesn't auto-play video folders

My files are organized thusly:

Movies/Genre/Title - Director - Year - Misc/VIDEO_TS
Movies/Genre/Title - Director - Year - Misc/movie.iso

I should be able to click on a folder to play the movie within. Currently I have to click on the .iso file, or on the VIDEO_TS file and then on the correct IFO file within! Absolutely, a VIDEO_TS folder should be considered a target. And if a folder contains only a single video target (and perhaps a few image or .nfo files) that folder should play when clicked on. There is a similar problem at XBMC toplevel - I have to select video, then files, before I can even start browsing. I would like to have my video sources and audio sources listed right at the toplevel. Overall it take me perhaps 8 clicks to play something when it should only take 4. Playing things from "library" rather than "files" context might help this. Enabling "stack" option might help this. Enabling stacking helps somewhat, but also introduces new problems. For instance, if I have a few .iso files laying around in a high-level directory full of folders with different movie collections, stacking treats that high-level folder as a target and plays when I click on it. So I either have to turn off stacking, or audit my filesystem for loose .iso and VIDEO_TS instances and put them all inside their own folders. Default stacking doesn't seem to be quite smart enough to behave properly in a typical real-word disorganized collection.

Browsing a certain folder causes XBMC to hang

Will debug by splitting the difference until I figure out what in that folder is causing the problem. TBD TBD