Shinobu’s Secrets

October 4, 2009

Linux Dual Monitor Setup: Nvidia & Xinerama Guide: Rotating just one monitor

Filed under: FYI, Linux — Shinobu @ 10:55 pm

I have 2 LCD monitors (both are widescreen) hooked up to an Nvidia card in Linux. For a while, I rotated both of them into a “portrait” view, because, aside from the other benefits a portrait view can give (to webpages and documents), putting two widescreens on a landscape configuration takes up too much horizontal space.

But yesterday, I decided to take a hybrid approach and put my left monitor in landscape view, but my right one into portrait view — i.e., I only wanted one monitor rotated 90 degrees. Of course, this is fairly straightforward in Windows with the proprietary Nvidia utility, but it takes a little bit of work with Linux. I googled around a bit, and found this page. I couldn’t really understand what was going on by just looking at the sample xorg.conf file on that page, so I decided to write out my usual in-depth explanation on the matter.

First, to get this hybrid approach, you have to use Xinerama, and NOT Nvidia’s popular TwinView utility/configuration. This is because TwinView (in Linux) only allows you to rotate BOTH monitors together in the same direction.

The only thing you have to do is edit your /etc/X11/xorg.conf file. First, if you already have TwinView set up to work in a dual monitor configuration, you have to run sudo nvidia-settings, and then change from “TwinView” to “Separate X screen” under the “X Server Display Configuration” settings, like so:

2009-10-04-133053_914x657_scrot

The reason we do this (if you already have nvidia-settings installed) is because it auto-generates a working xorg.conf for us. The thing is, under TwinView, you just have 1 option for everything in Xorg — i.e., you just have Device0, Screen0, Monitor0, but now with the “Separate X screen”, you have Device1, Screen1, etc. Not only that, but your old, irrelevant TwinView settings will be automatically deleted or commented out, so it will save you a couple minutes of work (and any typos as well — typos will prevent X from booting!). After that, it’s just a matter of tweaking the xorg.conf file to suit your needs. (BTW, the reason why the right monitor looks like it’s not aligned vertically correctly with the one on the left is because of a manual adjustment — it’s the 333 pixel shift adjustment I made; read on below for more on that).

Here is my current, working xorg.conf with just 1 monitor rotated:

  1 Section "ServerLayout"
  2     Identifier     "Layout0"
  3     #Screen      0  "Screen0" RightOf "Screen1" # put it on the RIGHT (other options are Below, Above, LeftOf, RightOf;
  4                                                 # alternatively, you can put an absolute, pixel X and Y offset (so RightOf
  5                                                 # would be 1680 0
  6     Screen      0  "Screen0" 1680 0 # NOTE: Screen 0 MUST be defined BEFORE Screen 1!!!
  7     Screen      1  "Screen1" 0 333 # put this screen on the top left, but adjust it down a little bit to match the portrait screen on the right
  8     InputDevice    "Keyboard0" "CoreKeyboard"
  9     InputDevice    "Mouse0" "CorePointer"
 10 EndSection
 11 
 12 Section "Files"
 13 EndSection
 14 
 15 Section "Module"
 16     Load           "dbe"
 17     Load           "extmod"
 18     Load           "type1"
 19     Load           "freetype"
 20     Load           "glx"
 21 EndSection
 22 
 23 Section "ServerFlags"
 24     Option         "AutoAddDevices" "False"
 25     Option         "Xinerama" "1"
 26 EndSection
 27 
 28 Section "InputDevice"
 29 
 30     # generated from default
 31     Identifier     "Mouse0"
 32     Driver         "mouse"
 33     Option         "Protocol" "auto"
 34     Option         "Device" "/dev/psaux"
 35     Option         "Emulate3Buttons" "no"
 36     #Option         "ZAxisMapping" "4 5" # for the Logitech MX 400
 37 EndSection
 38 
 39 Section "InputDevice"
 40     Identifier     "Keyboard0"
 41     Driver         "kbd"
 42     Option         "XkbModel" "pc105"
 43     Option         "XkbLayout" "us,fr,de"
 44     Option         "XkbOptions" "grp:shifts_toggle"
 45 EndSection
 46 
 47 Section "Monitor"
 48     Identifier     "Monitor0"
 49     VendorName     "Unknown"
 50     ModelName      "Acer X222W"
 51     HorizSync       31.0 - 81.0
 52     VertRefresh     56.0 - 75.0
 53     Option         "DPMS"
 54     Option         "Rotate" "Right" # for portrait mode
 55 EndSection
 56 
 57 Section "Monitor"
 58     Identifier     "Monitor1"
 59     VendorName     "Unknown"
 60     ModelName      "Acer X222W"
 61     HorizSync       31.0 - 81.0
 62     VertRefresh     56.0 - 75.0
 63     Option         "DPMS"
 64 EndSection
 65 
 66 Section "Device"
 67     Identifier     "Device0"
 68     Driver         "nvidia"
 69     VendorName     "NVIDIA Corporation"
 70     BoardName      "GeForce 8800 GTS"
 71     Option         "RandRRotation" "on"
 72     BusID          "PCI:1:0:0"
 73     Screen          0 # i.e., the monitor on the RIGHT (physically)
 74 EndSection
 75 
 76 Section "Device"
 77     Identifier     "Device1"
 78     Driver         "nvidia"
 79     VendorName     "NVIDIA Corporation"
 80     BoardName      "GeForce 8800 GTS"
 81     BusID          "PCI:1:0:0"
 82     Screen          1 # the monitor on the LEFT (physically)
 83 EndSection
 84 
 85 Section "Screen"
 86 
 87     Identifier     "Screen0"
 88     Device         "Device0"
 89     Monitor        "Monitor0"
 90     DefaultDepth    24
 91     Option         "metamodes" "DFP-0: 1680x1050 +0+0"
 92     SubSection     "Display"
 93         Depth       24
 94     EndSubSection
 95 EndSection
 96 
 97 Section "Screen"
 98     Identifier     "Screen1"
 99     Device         "Device1"
100     Monitor        "Monitor1"
101     DefaultDepth    24
102     Option         "metamodes" "DFP-1: 1680x1050 +0+0"
103     SubSection     "Display"
104         Depth       24
105     EndSubSection
106 EndSection
107

Probably the most important options are the “Screen” options under the “ServerLayout” section — these define which monitor starts where, and the relationship between the two monitors. The “Screen” options are defined by a X-axis (horizontal) and Y-axis (vertical) offset — you can only use positive numbers, I think, and so this means that if a screen is defined as “0 0″, it is on the top left corner of the imaginary monitor “plane,” so to speak. I.e., increasing the X-axis offset moves your screen to the right, whereas increasing the Y-axis offset moves your screen down. For me, my left monitor is slightly adjusted down by 333 pixels, so that it matches up smoothly with my rotated monitor on my right (my setup, physically, looks like a sideways “T”). I’m not sure if the “RandRRotation” option is necessary — it probably is not — I’m too lazy to check after fiddling with my xorg.conf all day yesterday. The other options should be self-explanatory, along with the comments.

Here are some of the not-so-obvious details: for me, my “DFP-1″ is my LEFT monitor and “DFP-0″ is my RIGHT monitor. Apparently, the “primary display” is by default DFP-o (e.g., in Windows, the Nvidia utility detects DFP-o (my RIGHT monitor) as screen “1 of 2″, so I have to manually set DFP-1 (2 of 2) as my primary screen) — the only reason why I have it like this is because for some reason, my BIOS stuff shows up on DFP-1, and not the default “primary” DFP-0, and I’ve always liked my BIOS to show up on my LEFT screen by default — hence the reason why DFP-1 is on my left and DFP-0 is on my right. I hope that made sense. It probably didn’t, so here is a screenshot:

2009-10-04-141105_2730x1680_scrot

Each monitor has a resolution of 1680×1050, but now, my virtual desktop has a 2730×1680 resolution (1680 + 1050 = 2730). DFP-0 is physically rotated so that the bottom side sticks out to the far right — i.e., it’s rotated counter-clockwise 90 degrees — so that the clean, button-less bezel of its top area matches up nicely with the unrotated DFP-1.  And so, we rotate “Right” under the “Monitor” section for Screen 0. This is probably the most sensible way for most people, since almost all monitors that do have buttons at all (to make an uneven, fatter bezel where the buttons are) have them at the bottom of the monitor.

Here are the advantages that you get with Xinerama in the above setup:

  • Moving the mouse from the right to the left is always continuous and seamless. This is even true when moving from the far edges of the portrait monitor into the widescreen one (see notes in screenshot). Finally, the virtual screen behaves EXACTLY like how the monitors look in the real world. (This behavior is available in Windows; however, there are two shortcomings that are not found in Xinerama: (1) when the mouse is on the top or  bottom edge of the portrait monitor, your mouse becomes “stuck” and does not transition smoothly over to the widescreen monitor on the other side (see screenshot above); (2) even though you can adjust the monitors by simply dragging the icons around (which is very user-friendly, I must say), the adjustments are very course and you cannot adjust things down to the last pixel.)
  • Maximizing a window maximizes to the monitor’s area (i.e., the window maximizes up to either the landscape or portrait view), and not the big, virtual landscape of 2730×1680 pixels; even the applications behave intelligently!

A (temporary) disadvantage:

  • Since I’m using Xmonad as my window manager, popup dialog boxes automatically spawn to to the top-left of the virtual screen — i.e., if they’re small enough, they fit entirely into the unviewable area on the top edge. I have to manually flatten the image into the tiled area to see the contents of it. However, this is Xmonad’s fault, and there is probably a hack out there to fix this sort of thing. Even so, since I don’t really use GUI applications that have a lot of popup dialog boxes in the first place, this is a non-issue.

For a long time I thought that Xinerama was an ATI thing, but apparently, it works for Nvidia as well. The xorg.conf layout looks much nicer, and simpler with Xinerama, and is much more flexible with it (e.g., the 333 pixel shift). If you change the few lines in my xorg.conf above that deal with rotations, you could even do without TwinView as well and just use Xinerama for a basic dual-head setup without any rotated screens.

September 14, 2009

Nvidia & Rotated Screen Partial Workaround

Filed under: FYI, Linux — Tags: — Shinobu @ 6:51 am

Currently, there is a bug in the latest Nvidia drivers for Linux. It is the bug described in the following threads:

I suffer from the same “border anomalies” because I too, use Xmonad and Nvidia drivers, with two rotated screens. I lived with the annoyance for a few months (I even emailed Nvidia a bug report), until, by accident, I discovered a partial workaround — for all urxvt terminal windows. Since I usually do all my important work in urxvt terminal windows anyway (only exceptions being firefox and maybe OOo Writer), it really is a lifesaver. The fix for urxvt windows is as follows: in your ~/.Xdefaults file, put in the following property for urxvt’s resources, like so:

urxvt*depth: 32

For some reason, this fixes the strange border behavior completely for all urxvt windows in Xmonad. I stumbled on this workaround when trying to make my urxvt windows transparent (which don’t work for me — probably because I use xwinwrap to play a screensaver permanently in the background).

BTW, I also use the option “urxvt*fading: 33″ to make inactive windows fade out a bit, even though this setting is a bit buggy at the moment (probably as a result of the xwinwrap thing and also how Nvidia’s drivers are still messing things up in the first place). Still, the fading option is worth a try if you haven’t done so yet — it’s much faster to recognize active urxvt windows than from just using xmonad’s border’s alone (I use a 1-pixel wide white/black border in xmonad).

UPDATE November 11, 2009: Nvidia’s latest driver, 190.42, seems to have fixed this issue. Rotated screen + border issue has been resolved according to their changelog, and I have noticed the change myself in my desktop’s rotated monitor.

July 23, 2009

Enable HQ Quality on any Youtube video

Filed under: FYI — Shinobu @ 1:39 am

Just add “&fmt=18″ to the video’s URL.

This is especially useful for screencasts done by programmers with small text.

March 31, 2009

Use your /etc/hosts file to save time

Filed under: FYI, Linux — Shinobu @ 7:40 am

I was installing Arch Linux on yet another machine (new laptop), and was pleasantly surprised by a little tidbit in the Arch Wiki pages — specifically the Beginner’s Guide (which is continually improved and updated fanatically by the Arch community). In short, you can alias host addresses in your /etc/hosts file. This can be for web addresses (www.google.com) or addresses on your LAN. Here is the example and explanation given by the wiki page:

“Tip: For convenience, you may also use /etc/hosts aliases for hosts on your network, and/or on the Web, e.g.:

64.233.169.103   www.google.com   g
192.168.1.90   media
192.168.1.88   data

The above example would allow you to access google simply by typing ‘g’ into your browser, and access to a media and data server on your network by name and without the need for typing out their respective IP addresses.”

Putting your hostname aliases in your /etc/hosts file is great, since all of your programs use it. Firefox, your terminal/shell, git, etc. They all reference this file. So if you’re using git, you can do git clone ssh://username@hostname-alias/… to clone a repo from your LAN, as I described in my post here, instead of ssh://username@192.168.0.2/…. So now all of your hosts on your LAN will be much easier to remember. Here’s my /etc/hosts file:

#
# /etc/hosts: static lookup table for host names
#
#<ip-address>    <hostname.domain.org>    <hostname>
127.0.0.1        aether.localdomain    aether
# aliases
192.168.0.20   exelion
192.168.0. 21 luxion.e
192.168.0.22   luxion.w
# End of file

I’ve aliased luxion.e to my laptop’s ethernet adapter, and luxion.w to its wireless adapter. After setting up your aliases in /etc/hosts, you should get in the habit of writing out your (sane) hostnames for all your LAN computers, instead of painfully writing out their numeric IP addresses. (And I’m sure you’d want to alias your hostnames even more with the advent of IPv6 — and its rather long IP address format.)

March 18, 2009

MPD – A Brief Guide

Filed under: FYI, Linux, Recreation — Tags: , , , , — Shinobu @ 5:24 am

The Music Player Daemon, aka MPD, is a great little application to handle music on your linux computer. Until recently (when Linux really started to take off and gain popularity), MPD has been notoriously difficult to get to work properly. I decided to write this small intro to MPD after having used it for about 6 months. This is a little guide to it to get you started on using MPD as your music manager.

The World of MPD

First, what MPD is:

  • MPD keeps track of your music library. It does this by defining a music directory, to which you can easily add symlinks to all the various places where you store your music on your computer.
  • MPD tracks changes to your music library (any time an mp3 is removed, or a new album added, you simply update the MPD database file — which takes three or four seconds at most).
  • MPD can store playlists.
  • MPD can play songs, and output this information to various devices, such as your physical speakers (via alsa usually, but it can be any audio driver for your system), or even a http port for web access (via icecast).

What MPD is NOT (what most people get confused about):

  • MPD cannot by itself determine: which songs are played and in what order. Nor does it come with any controls such as PAUSE, STOP, NEXT TRACK, etc. MPD, quite simply, can either: play a song, or do nothing while it is running. MPD’s behavior is controlled by clients, such as GMPC, Sonata, etc (my personal favorite is ncmpcpp).

The downside of this dichotomy between what MPD is and what it is not, is that you must install two applications to get the same functionality as any standard multimedia player like iTunes. However, there are many, many advantages of splitting up music-playing from music-controls. First, mpd will hardly crash and will be error-free due to its simple nature. Second, you gain the ability to access your large music collection from other computers in your home network without much fuss. This means that you could do things like: make your laptop act as a remote controller for your desktop’s speakers, or even create multiple MPD instances for specific purposes (e.g., alsa vs. icecast output).

Typical Setup

For most people, they only need one instance of MPD running — configured so that it plays songs directly to their computer speakers (with alsa output). So their MPD configuration file will look something like this (comment lines removed to save space):

music_directory "/home/shinobu/.mpd-untracked/music"
playlist_directory "/home/shinobu/.mpd-untracked/playlist"
db_file "/home/shinobu/.mpd-untracked/mpd.db"
log_file "/home/shinobu/.mpd-untracked/mpd.log"
error_file "/home/shinobu/.mpd-untracked/mpd.error"
pid_file "/home/shinobu/.mpd-untracked/mpd.pid"
state_file "/home/shinobu/.mpd-untracked/mpdstate"
user "shinobu"
bind_to_address        "localhost" # if no one else on the LAN wants to use this mpd; otherwise use local IP address
port                "6600"
audio_output {
    type            "alsa"
    name            "Exelion ALSA output"
}
mixer_type            "alsa"
mixer_device            "default"
mixer_control            "PCM"
replaygain            "track"
filesystem_charset        "UTF-8"
id3v1_encoding            "ISO-8859-1"

It’s very straightforward. All of the essential files and folders are customized and defined in the config file. (My mpd directory is .mpd-untracked, since these files/folders are not tracked by my git folder containing all of my dotfiles. See my previous two posts for more info on that setup.) The config file itself resides at /home/shinobu/sycfg/mpd/cfg-alsa — a customized path and filename, which is referenced each time MPD starts on bootup (in my .xinitrc file), with the command “mpd /home/shinobu/syscfg/mpd/cfg-alsa”. MPD will daemonize itself when it is called, so calling it from your .xinitrc file without the “&” argument at the end of the line is OK. Notice how the above configuration avoids running into permission problems, since everything resides under a normal user’s directory.

I then start up ncmpcpp, which by default looks to the mpd host as localhost and port as 6600 — matching the (default) values in my MPD config file above. And it all works rather beautifully.

Multi-MPD Setup for Music Sharing

Back when I still used iTunes (about 3 years ago), I remember it had this neat feature to share your music with anyone on your local network. You can do the same thing with MPD. The trick is to add a separate MPD instance for this very same feature. I myself have this multi-MPD setup on my desktop, with one MPD for alsa-only output (as seen above), and a second MPD for icecast-only output. Icecast, by the way, is a more general solution not wholly related to MPD for sharing music over the internet — we can use icecast since it plays rather well with MPD. Since my desktop has a second MPD instance so that it works with icecast, my laptop can now take advantage of the huge music collection that I have on it, remotely (well, as long as I’m on the home network in my case).

Here’s my MPD config file for icecast output:

music_directory "/home/shinobu/.mpd-untracked/music"
playlist_directory "/home/shinobu/.mpd-untracked/playlist"
db_file "/home/shinobu/.mpd-untracked/mpd.db"
log_file "/home/shinobu/.mpd-untracked/mpd-icecast.log"
error_file "/home/shinobu/.mpd-untracked/mpd-icecast.error"
pid_file "/home/shinobu/.mpd-untracked/mpd-icecast.pid"
state_file "/home/shinobu/.mpd-untracked/mpdstate-icecast"
user "shinobu"
bind_to_address		"192.168.0.7" # bind it to this computer's IP address if someone on the LAN wants to use this mpd
port				"6601"
audio_output {
    type			"shout"
    name			"exelion HD mpd stream"
    encoding		"ogg"			# optional
    host			"localhost"
    port			"8000"
    mount			"/mpd.ogg"
#--------------------------------------------------------------------------------------------------#
# See 'source password' in /etc/icecast.xml for password                                           #
#--------------------------------------------------------------------------------------------------#
    password		"hackme"
#--------------------------------------------------------------------------------------------------#
# Use 'bitrate' or 'quality'. Use 'bitrate' for static bitrate, or 'quality' for variable.         #
# Use one or the other -- not both!                                                                #
# bitrate                     "128"                                                                #
#--------------------------------------------------------------------------------------------------#
    quality			"10"
#--------------------------------------------------------------------------------------------------#
# 'format' is the audio format of the stream. The first number is the sample rate in Hertz (Hz);   #
# 44100 Hz is equal to cd quality. The second number is the number of bits per sample; again 16    #
# bits is the quality used on cd's. The third number is the number of channels; 1 channel is       #
# mono, 2 channels is stereo.                                                                      #
#--------------------------------------------------------------------------------------------------#
    format			"44100:16:2"
    protocol		"icecast2"		# optional
    user			"source"		# optional
    #description		"My Stream Description"	# optional
    #genre			"jazz"			# optional
    #public			"no"			# optional
    #timeout			"2"			# optional
}
mixer_type			"alsa"
mixer_device			"default"
mixer_control			"PCM"
replaygain			"track"
filesystem_charset		"UTF-8"
id3v1_encoding			"ISO-8859-1"

As you can see, much of the configuration is exactly the same as my first MPD config file. You’d want it like this, since you’d want it to use the same music collection and list of playlists. So the music directory, playlist directory, and database file are all the same. However, you’d want a different set of logfiles for this second MPD instance, so those values are changed. The same goes to the pid and state files.  The other noticeable differences are the bind_to_address value, set to my desktop’s IP address. The port number is also 6601, so that it doesn’t conflict with my first MPD. The final difference is the audio output, which is set to “shout” and not “alsa”. The “shout” output works with icecast, and the values in here, like port 8000 and “hackme” as the password, are taken straight from the default icecast intallation’s xml file (/etc/icecast.xml — of course, you can call icecast with a different config file location than the default one).

It’s important that you make this second MPD output solely to icecast. If you put in alsa output here, you’d have two different songs playing simultaneously on your desktop’s speakers! (Aside: MPD is perfectly capable of outputting to multiple audio outputs, so you could, if you wanted, make one MPD instance output to both alsa and icecast — although I don’t see why anyone would do this.) As for icecast itself, you can also call it from your .xinitrc file, after your mpd-calling lines, like so: icecast -b -c /home/shinobu/syscfg/icecast/cfg.xml. The -b flag daemonizes icecast (required since you’re calling it from your .xinitrc file), and the -c flag merely points to the correct config file location. My icecast config file looks like this:

<icecast>
    <limits>
        <clients>100</clients>
        <sources>2</sources>
        <threadpool>5</threadpool>
        <queue-size>524288</queue-size>
        <client-timeout>30</client-timeout>
        <header-timeout>15</header-timeout>
        <source-timeout>10</source-timeout>
        <burst-on-connect>1</burst-on-connect>
        <burst-size>65535</burst-size>
    </limits>
    <authentication>
        <source-password>hackme</source-password>
        <relay-password>hackme</relay-password>
        <admin-user>admin</admin-user>
        <admin-password>hackme</admin-password>
    </authentication>
    <hostname>localhost</hostname>
    <listen-socket>
        <port>8000</port>
    </listen-socket>
    <fileserve>1</fileserve>
    <paths>
        <basedir>/usr/share/icecast</basedir>
        <logdir>/home/shinobu/.icecast-untracked/log</logdir>
        <webroot>/home/shinobu/.icecast-untracked/icecast/web</webroot>
        <adminroot>/home/shinobu/.icecast-untracked/icecast/admin</adminroot>
        <alias source="/" dest="/status.xsl"/>
    </paths>
    <logging>
        <accesslog>access.log</accesslog>
        <errorlog>error.log</errorlog>
        <loglevel>1</loglevel> <!-- 4 Debug, 3 Info, 2 Warn, 1 Error -->
        <logsize>10000</logsize> <!-- Max size of a logfile -->
    </logging>
    <security>
        <chroot>0</chroot>
    </security>
</icecast

Here, the value for the <source-password> tag must match the password specified in your icecast-MPD’s config file. I’ve left it to the default “hackme” here for demnstration purposes — you should change it to something more secure (better safe than sorry!). My password is like @#$k23lsdf9. Make sure the directory in <logdir> exists. As for the <webroot> and <adminroot> directories, copy them straight out of /usr/share/icecast/web and /usr/share/icecast/admin, and place them into your custom location. This will take care of those annoying permission errors that users often face.

Now, on your remote computer, such as your laptop, you need (1) an MPD client, and (2) a music player, like mplayer, to intercept the raw .ogg music stream from your desktop with the icecast-MPD setup. In my ncmpcpp config file on my laptop, I have custom values for the mpd_host and mpd_port fields to be my desktop’s IP address 192.168.0.7 and 6601, respectively (matching the values in the second MPD config file above). So when I fire up ncmpcpp on my laptop, it connects over the LAN network into the music collection residing in my desktop, all with the magic of MPD. Once I activate the ogg stream by playing a file, I can then access this stream with mplayer — specifically, with mplayer -ao alsa -softvol -volume 10 -volstep 1 -prefer-ipv4 http://192.168.0.110:8000/mpd.ogg. I have this long command aliased, of course, to a hotkey in my XMonad configuration file. And within a couple seconds, I get a top-quality, ~500 kbps ogg stream right on my laptop (the quality setting in my MPD config file, set to “10″, is the maximum quality supported by the ogg format; 500 kbps, or a little over 60 KBps, should be nothing on your home ethernet LAN).

So here’s what’s happening with this second MPD instance on my desktop, configured with icecast output: MPD is keeps tabs on what my music collection consists of from port 6601, and “plays” to port 8000 — converting my current mp3/flac file into an ogg stream, which is then served by icecast. From my laptop, I then connect to this MPD by the desktop’s IP address and MPD port of 6601 with ncmpcpp. Then, once I tell MPD to start playing, I can then access the ogg stream with mplayer on my laptop. Mplayer simply looks to http://192.168.0.7:8000/mpd.ogg. When icecast on my desktop receives this request from my laptop’s mplayer, it gives the go-ahead and essentially acts as a bridge between my desktop’s icecast-output MPD and my laptop’s mplayer. Mplayer then takes this ogg stream, and outputs it onto my laptop’s speakers using the alsa drivers.

Here’s a picture to describe what’s going on. (The latest OpenOffice.org Drawing app is really a pleasure to use!)

mpd-configurationSo I hope this post proves useful to people who are new to Linux and are struggling to get MPD (and especially with Icecast) to work.

March 17, 2009

Unified Configuration File Setup Across Multiple Machines – Revisited

Filed under: FYI, Linux, Productivity/Perspectives — Shinobu @ 11:49 pm

My last post discussed how to get your config files, known as “dotfiles,” synchronized across multiple machines using a rudimentary makefile and git. I said that I hoped of achieving the “one folder for all config files” dream. I have achieved it, and it is pretty simple. Also, I will discuss how to handle files with passwords in them, and some other thoughts on this setup.

Keep track of system files, too

Essentially, my last post left out all but the system configuration files, such as /etc/fstab and the like. The /etc folder is owned by root, as well as the /boot folder. My first approach was to simply replace all such files with more symlinks, which would point to files owned by the normal user of the system. This approach had its drawbacks: (1) not all system files are symlinkable (e.g., /etc/sudoers is particularly security-conscious), and (2) the idea of deleting system files and replacing them with symlinks, on its face, sounded like I was setting myself up for a big grand screw-up.

So I thought: “Well, since system files are seldom ever edited anyway, why not just back them up periodically?” And that’s what I did instead. Now my makefile, as discussed in the previous post, has a section like this:

# copy contents of system files to keep track of them
syscopy:
ifeq ('$(HOSTNAME)','exelion')
	cat /boot/grub/menu.lst >       /home/shinobu/syscfg/sys/boot-grub-menu.lst-exelion
	cat /etc/X11/xorg.conf >        /home/shinobu/syscfg/sys/etc-X11-xorg.conf-exelion
	cat /etc/fstab >                /home/shinobu/syscfg/sys/etc-fstab-exelion
	cat /etc/hosts >                /home/shinobu/syscfg/sys/etc-hosts-exelion
	cat /etc/inittab >              /home/shinobu/syscfg/sys/etc-inittab-exelion
	cat /etc/makepkg.conf >         /home/shinobu/syscfg/sys/etc-makepkg.conf-exelion
	cat /etc/rc.conf >              /home/shinobu/syscfg/sys/etc-rc.conf-exelion
	cat /etc/rc.local >             /home/shinobu/syscfg/sys/etc-rc.local-exelion
	cat /etc/rc.local.shutdown >    /home/shinobu/syscfg/sys/etc-rc.local.shutdown-exelion
	cat /etc/yaourtrc >             /home/shinobu/syscfg/sys/etc-yaourtrc-exelion
	cat /etc/sudoers >              /home/shinobu/syscfg/sys/etc-sudoers-exelion # requires superuser privileges to read!
else
	cat /boot/grub/menu.lst >       /home/shinobu2/syscfg/sys/boot-grub-menu.lst-luxion
	cat /etc/X11/xorg.conf >        /home/shinobu2/syscfg/sys/etc-X11-xorg.conf-luxion
	cat /etc/fstab >                /home/shinobu2/syscfg/sys/etc-fstab-luxion
	cat /etc/hosts >                /home/shinobu2/syscfg/sys/etc-hosts-luxion
	cat /etc/inittab >              /home/shinobu2/syscfg/sys/etc-inittab-luxion
	cat /etc/makepkg.conf >         /home/shinobu2/syscfg/sys/etc-makepkg.conf-luxion
	cat /etc/network.d/luxion-wired > /home/shinobu2/syscfg/sys/etc-network.d-luxion-wired
	cat /etc/network.d/luxion-wireless-home-nopassword > /home/shinobu2/syscfg/sys/etc-network.d-luxion-wireless-home-nopassword
	cat /etc/rc.conf >              /home/shinobu2/syscfg/sys/etc-rc.conf-luxion
	cat /etc/rc.local >             /home/shinobu2/syscfg/sys/etc-rc.local-luxion
	cat /etc/rc.local.shutdown >    /home/shinobu2/syscfg/sys/etc-rc.local.shutdown-luxion
	cat /etc/yaourtrc >             /home/shinobu2/syscfg/sys/etc-yaourtrc-luxion
	cat /etc/sudoers >              /home/shinobu2/syscfg/sys/etc-sudoers-luxion
endif

I have in my /etc/rc.local the command “make -f /path/to/the/above/makefile -B syscopy“. So every time my system boots up, all of the config files are copied into their backup-equivalents in the syscfg/sys folder. Since git tracks changes in the syscfg folder, only changes in the config files are detected and tracked as changes (i.e., git doesn’t track changes in file modification times, which is a good thing here for our purposes — otherwise git would be saying that every time we boot up all of our system files have changed!). So now all of my system config files are tracked passively (by merely reading off them). Of course, if I manually edit a system file, I can still call make -B syscopy myself manually, and then run git diff in the syscfg folder to track those changes, and then git commit to solidify those changes into the git history.

For config files with passwords in them

DO NOT EVER PUT CONFIG FILES WITH PASSWORDS INTO YOUR TRACKED DOTFILES FOLDER! Not only does this mean that your password, in plain text, is tracked by git, but that should you ever change your password, git will notice the changes and track them as well! This will give anyone who gets access to your git repo a complete, timestamped history of your passwords for your applications (like icecast, irssi, etc.) So to get around this problem, I have it set up so that I have a copy of the password-containing config file, minus the passwords in them. Whenever I make changes to the original password-containing files, I update the changes into the copies, and then track these copies in git, not the originals.

Not all config files need symlinks

In my last post, I discussed how creating symlinks via commands in the makefile was the key to this whole setup. But for some (smarter) applications, symlinks are not needed, since they can intelligently be told which config file to use. Alpine, icecast, irssi, and mpd are like this, so I just have config files for them inside my syscfg folder, and just run these apps (which are all autostarted for me each time on boot) with commandline parameters pointing to the non-default config file locations.

March 9, 2009

Unified Configuration File Setup Across Multiple Machines

Filed under: FYI, Git, Linux, Productivity/Perspectives — Tags: , , , , , — Shinobu @ 3:40 am

SUMMARY: This post shows you how to sync multiple configuration files across multiple hosts with git and a makefile.

INTRODUCTION

If you have 20 different so-called ‘dotfiles’ like me, they can get difficult to keep track of. It can be even more difficult if you have multiple computers that you use often, and if you want them all to be updated to your latest settings.

For myself, I need to keep track of:

  • .gitconfig
  • .zshrc
  • .zsh (folder)
  • .vim (folder)
  • .vimrc
  • .gvimrc
  • .vimperatorrc
  • .Xdefaults
  • .boxes
  • .xmonad (folder)
  • .xmonad/init.sh (custom init script that XMonad is told to call in the startup hook)
  • .xmonad/xmonad.hs
  • shellscripts (folder which has a growing number of custom shell scripts that I like to use every now and then, or at least keep as a reference on both my desktop and laptop)
  • .xinitrc

Of course, this list will grow over time, as I start to learn more things and begin using more programs. What I want to do is (1) copy these files over to any other host that I use/own automatically and sync back to all the other machines any changes that I make to any one particular machine; and (2) have a unified config file structure, with a directory name for the application/setting, and a simple file called ‘cfg’ for the config file (which will be symlinked to what the application thinks is the true, appropriate location of the config file). The great thing about these two issues is that there is a simple, durable solution for these two precise concerns: git and make. So enough blabbering, let’s get to it!

Step 1: Put all config files into a new directory

It doesn’t matter where your new directory (let’s call it syscfg) is located. Move all of your config files that you want to keep track of into this directory. I suggest you rename all of them to fit some kind of unified naming scheme, and take note of what their former names/destinations used to be. For example, I use syscfg/vim to keep all of my vim things in there (instead of the default .vim, including a file called cfg to act as my .vimrc file).

Per-host (host-specific) settings

I highly suggest that you make all of your config files, such as your .xinitrc (or any other script or some sort) file, include per-host specific settings. Otherwise, you will have the same config settings on all of your systems! I.e., you’d want your .xinitrc to have something like:

do-something-universal-here
HOSTNAME=$(hostname)
case "${HOSTNAME}" in
    hostname1)
    do-something-here
    ;;
    hostname2)
    do-something-else-here
    ;;
    *) # catches all other hostnames
    do-something-else-that's-universal-here
    ;;
esac
do-something-else-that's-universal-here

The above syntax is for bash scripts (files that start with a “#!/bin/bash” at the very first line). If you are using zsh, you could also use this syntax for creating aliases that are specific to a certain host (e.g., my laptop doesn’t have 2 hard drives, so it doesn’t have aliases that point to my mount directory).

If your config file is painful to work with in implementing per-host settings (my xmonad.hs file is like this), you can still achieve per-host settings by making 2 config files, so for example cfg-host1 and cfg-host2, and symlink the correct one to .xmonad/xmonad.hs. You determine the correct config file to symlink to in the makefile. Read on.

Step 2: Create a makefile

Your sysconfig should now have a clean, uniform structure for all of your config files. Now, let’s create a makefile so that the program make can install and uninstall the symlinks as necessary. Here’s what my makefile looks like:

CFGROOT := $(shell pwd)
HOSTNAME := $(shell hostname)
all: boxes git shellscripts vim vimperatorrc xdefaults xinitrc xmonad zsh
boxes:
	ln -fs $(CFGROOT)/boxes/cfg ${HOME}/.boxes
git:
	ln -fs $(CFGROOT)/git/cfg ${HOME}/.gitconfig
shellscripts:
	ln -fs $(CFGROOT)/shellscripts ${HOME}/shellscripts
vim:
	ln -fs $(CFGROOT)/vim ${HOME}/.vim
	ln -fs $(CFGROOT)/vim/cfg ${HOME}/.vimrc
	ln -fs $(CFGROOT)/vim/cfg-gui ${HOME}/.gvimrc
vimperatorrc:
	ln -fs $(CFGROOT)/vimperatorrc/cfg ${HOME}/.vimperatorrc
xdefaults:
	ln -fs $(CFGROOT)/xdefaults/cfg ${HOME}/.Xdefaults
xinitrc:
	ln -fs $(CFGROOT)/xinitrc/cfg ${HOME}/.xinitrc
xmonad:
	ln -fs $(CFGROOT)/xmonad ${HOME}/.xmonad
	ln -fs $(CFGROOT)/xmonad/init ${HOME}/.xmonad/init.sh
#--------------------------------------------------------------------------------------------------#
# Since it's really painful to do a unified config file across multiple hosts in XMonad v. 0.8.1,  #
# I have to do it this way.                                                                        #
#--------------------------------------------------------------------------------------------------#
ifeq ('$(HOSTNAME)','exelion')
	ln -fs $(CFGROOT)/xmonad/cfg ${HOME}/.xmonad/xmonad.hs
else
	ln -fs $(CFGROOT)/xmonad/cfg-luxion ${HOME}/.xmonad/xmonad.hs
endif

zsh:
	ln -fs $(CFGROOT)/zsh ${HOME}/.zsh
	ln -fs $(CFGROOT)/zsh/cfg ${HOME}/.zshrc

uninstall:
	rm ${HOME}/.boxes
	rm ${HOME}/.gitconfig
	rm ${HOME}/.vim
	rm ${HOME}/.vimrc
	rm ${HOME}/.gvimrc
	rm ${HOME}/shellscripts
	rm ${HOME}/.vimperatorrc
	rm ${HOME}/.Xdefaults
	rm ${HOME}/.xinitrc
	rm ${HOME}/.xmonad/init.sh
	rm ${HOME}/.xmonad/xmonad.hs
	rm ${HOME}/.xmonad
	rm ${HOME}/.zsh
	rm ${HOME}/.zshrc

This is where symlinks reveal their beauty. From what I know of Windows XP (and my knowledge is very limited because I hate M$ with a passion), you cannot do something like this. Anyway, the above is fairly obvious and straightforward, isn’t it? All this does is create symlinks, and remove them if desired. Since they are symlinks, you can still do something like “vim ~/.vimrc”, and vim will read (assuming again that our directory is syscfg) syscfg/vim/cfg, with all of the pretty syntax highlighting and so on. The -f flag for the ln command simply makes it create the symlink even if the symlink already exists at the destination. See man ln for more info.

If you run make -B all, it will create all the symlinks defined under the keyword all. (The -B flag, for forcing make to run, is required here given our situation with symlinks.) You could in the alternative select only those config files you wish to install; e.g., make -B xmonad for installing only those symlinks for vim’s config files, or make -B vim zsh for vim and zsh’s config files. Lastly, running make uninstall removes all of the symlinks from your system. Experiment to your delight. (Make sure to have the lines with ln and rm start with a TAB character, as make will otherwise throw an error.)

Also, note how the contents in syscfg do not matter at all in how they are named, since it’s really the with its symlinks that takes care of all the proper “dotfile” namings.

Lastly, since these are all symlinks, you can have in your, say, .gvimrc file, a line that says “source ~/.vim/cfg”, and it will still work since the .vim directory is symlinked to your syscfg/vim (i.e., you don’t have to refer to symlinks once you make the symlinks). This is just a long-winded way of saying that using this symlink approach preserves all of your old config file paths from within your config files.

Step 3: Fire up git

Now, fire up git, add your config files, and sync it across all your computers! Use my post here to do this. The only thing to note here for our purposes is that the makefile is stored under syscfg, and that syscfg is where git should be initialized (with git init). Also, only add the config files and any other files that the config files depend on. An example of a file you should NOT want to add to git is any sort of history file, such as zsh’s history file (specified with the HISTFILE option in zsh’s config file — in our case, syscfg/zsh/cfg), since you’d want different session history files for different machines. Another example would be vim’s session files for the session manager plugin. If you add such temporary history files (or any other file that the application automatically makes changes to), you will make git track these changes (very doable, but utterly worthless)! On the other hand, you’d probably want to add simply script-like files that your configs depend on, such as vim’s various plugins (mere .vim text files in the syscfg/vim directory), or even irssi’s perl plugins, if you use irssi (I don’t use IRC on my laptop, hence it’s exclusion from my sample syscfg and makefile above).

With git taking care of the syncing, you now have complete revision history, as well as guaranteed config file integrity across all of your systems. It’s only a matter of cloning, then simply pushing and pulling for all of your config file syncing needs. Personally, I have it set up so that I just do “sl” to ssh into my laptop (sl is aliased to the unbearably long “ssh username@192.168.0.102″; no password since I have ssh set up that way; again, see my post above to do this), then “d sy[TAB]” (“d” is aliased in my syscfg/zsh/cfg to mean “cd”, and I only have one directory starting with “sys” so I can use zsh’s TAB completion to do the rest), and then “gpl” (extremely shortened form for “git pull” — again, see my post on git to make git accept this instead of “git pull origin master”). Yes, all I do is sl, d sy[TAB], gpl, and my laptop is synced. No more checking/rechecking manually whether certain symlinks exist on my laptop, and whether certain vim plugins already exist on it. I wish I had thought of this sooner, as it would have saved me a lot of time.

Reminders and other tips

  • Make sure that all of your crucial config files (like .xinitrc) work properly before implementing this setup! (It’s not fun fixing things in the virtual console a la CTRL+ALT+.)
  • Make sure to have per-host settings in each of your config files (or, failing that, have your makefile link intelligently to different config files on a per-host basis)
  • In my vim config files above, you’ll notice that I symlink my cfg-gui to .gvimrc. The actual cfg-gui file looks very simple, with a “source ~/.vim/cfg”, and all the gvim-specific commands following that. Make sure to have a check for any autocommands so that they are loaded only once so that gvim works properly. (I must say, I only use vim now, except when I feel like seeing 16+ million colors (GTK) as opposed to 256 (urxvt).)
  • The makefile, and its contents, can be scripted in a different programming language if you don’t want to use make. I’ve noticed that some people use ruby to do this. But it could also be python, perl, bash, or any other script.
  • Since we’re going to end up putting into syscfg most of our config files, it wouldn’t be a bad idea to add files that don’t actually need syncing (see my note on irssi above). You’d just put an if-statement in your makefile to exclude these files for certain hosts. The benefit to this approach is that, you would end up with ONE git repo for ALL of your config files. Even though I’m not at this stage yet, I feel myself inevitably being pulled toward this path. I want complete revision history for all my /etc/X11/xorg.conf, /etc/fstab, /etc/sudoers, and even /boot/grub/menu.lst files, if it’s possible to do so. It’s probably a security risk to symlink to these destinations (file permissions, which git isn’t good at, at least according to what I heard from Linus’s Google Tech Talk from 2007), but I’m the only human who has access (and cares about) the config files on my desktop/laptop anyway. I’ll update this post if I end up achieving this “one config directory to rule them all” dream.

This guide was prepared with the help of various internet websites (google is your friend), and also especially this site.

February 11, 2009

Rails and SASS

Filed under: FYI, Rails, Ruby — Shinobu @ 11:11 am

I don’t think people quite understand the beauty and power of SASS (metaprogramming/abstraction layer on top of CSS).

Here is a small portion of a CSS file that is generated by SASS that I use on my personal (LAN) website. As WordPress doesn’t yet feature pretty code snippet tags, I have to use the “Preformatted” style for code — but the code here is too long for this design layout, you must  scroll allllll the way to the right to see all the code (alternatively, I suggest you copy all the text on this page and paste it into your text editor to get a real world feel on the sheer length of the code). I can’t help but marvel at the seemingly insane complexity of this VALID, working CSS code:

#article_body_unique .b_c_padding_bottom table.bullet, #article_body_unique .ph1b table.bullet, #article_body_unique .ph2b table.bullet, #article_body_unique .ph3b table.bullet, #article_body_unique .ph4b table.bullet, #article_body_unique .ph5b table.bullet, #article_body_unique .ph6b table.bullet, #article_body_unique .ph7b table.bullet, #article_body_unique .ph8b table.bullet, #article_body_unique .ph9b table.bullet, #article_body_unique .ph1c table.bullet, #article_body_unique .ph2c table.bullet, #article_body_unique .ph3c table.bullet, #article_body_unique .ph4c table.bullet, #article_body_unique .ph5c table.bullet, #article_body_unique .ph6c table.bullet, #article_body_unique .ph7c table.bullet, #article_body_unique .ph8c table.bullet, #article_body_unique .ph9c table.bullet, #article_body_unique .ph1d table.bullet, #article_body_unique .ph2d table.bullet, #article_body_unique .ph3d table.bullet, #article_body_unique .ph4d table.bullet, #article_body_unique .ph5d table.bullet, #article_body_unique .ph6d table.bullet, #article_body_unique .ph7d table.bullet, #article_body_unique .ph8d table.bullet, #article_body_unique .ph9d table.bullet, #article_body_unique .ph1e table.bullet, #article_body_unique .ph2e table.bullet, #article_body_unique .ph3e table.bullet, #article_body_unique .ph4e table.bullet, #article_body_unique .ph5e table.bullet, #article_body_unique .ph6e table.bullet, #article_body_unique .ph7e table.bullet, #article_body_unique .ph8e table.bullet, #article_body_unique .ph9e table.bullet, #article_body_unique .ph1f table.bullet, #article_body_unique .ph2f table.bullet, #article_body_unique .ph3f table.bullet, #article_body_unique .ph4f table.bullet, #article_body_unique .ph5f table.bullet, #article_body_unique .ph6f table.bullet, #article_body_unique .ph7f table.bullet, #article_body_unique .ph8f table.bullet, #article_body_unique .ph9f table.bullet {
  padding-left: 0.9em; }
#article_body_unique .b_c_padding_bottom table.bullet2, #article_body_unique .ph1b table.bullet2, #article_body_unique .ph2b table.bullet2, #article_body_unique .ph3b table.bullet2, #article_body_unique .ph4b table.bullet2, #article_body_unique .ph5b table.bullet2, #article_body_unique .ph6b table.bullet2, #article_body_unique .ph7b table.bullet2, #article_body_unique .ph8b table.bullet2, #article_body_unique .ph9b table.bullet2, #article_body_unique .ph1c table.bullet2, #article_body_unique .ph2c table.bullet2, #article_body_unique .ph3c table.bullet2, #article_body_unique .ph4c table.bullet2, #article_body_unique .ph5c table.bullet2, #article_body_unique .ph6c table.bullet2, #article_body_unique .ph7c table.bullet2, #article_body_unique .ph8c table.bullet2, #article_body_unique .ph9c table.bullet2, #article_body_unique .ph1d table.bullet2, #article_body_unique .ph2d table.bullet2, #article_body_unique .ph3d table.bullet2, #article_body_unique .ph4d table.bullet2, #article_body_unique .ph5d table.bullet2, #article_body_unique .ph6d table.bullet2, #article_body_unique .ph7d table.bullet2, #article_body_unique .ph8d table.bullet2, #article_body_unique .ph9d table.bullet2, #article_body_unique .ph1e table.bullet2, #article_body_unique .ph2e table.bullet2, #article_body_unique .ph3e table.bullet2, #article_body_unique .ph4e table.bullet2, #article_body_unique .ph5e table.bullet2, #article_body_unique .ph6e table.bullet2, #article_body_unique .ph7e table.bullet2, #article_body_unique .ph8e table.bullet2, #article_body_unique .ph9e table.bullet2, #article_body_unique .ph1f table.bullet2, #article_body_unique .ph2f table.bullet2, #article_body_unique .ph3f table.bullet2, #article_body_unique .ph4f table.bullet2, #article_body_unique .ph5f table.bullet2, #article_body_unique .ph6f table.bullet2, #article_body_unique .ph7f table.bullet2, #article_body_unique .ph8f table.bullet2, #article_body_unique .ph9f table.bullet2 {
  padding-left: 1.8em; }
#article_body_unique .b_c_padding_bottom table.bullet3, #article_body_unique .ph1b table.bullet3, #article_body_unique .ph2b table.bullet3, #article_body_unique .ph3b table.bullet3, #article_body_unique .ph4b table.bullet3, #article_body_unique .ph5b table.bullet3, #article_body_unique .ph6b table.bullet3, #article_body_unique .ph7b table.bullet3, #article_body_unique .ph8b table.bullet3, #article_body_unique .ph9b table.bullet3, #article_body_unique .ph1c table.bullet3, #article_body_unique .ph2c table.bullet3, #article_body_unique .ph3c table.bullet3, #article_body_unique .ph4c table.bullet3, #article_body_unique .ph5c table.bullet3, #article_body_unique .ph6c table.bullet3, #article_body_unique .ph7c table.bullet3, #article_body_unique .ph8c table.bullet3, #article_body_unique .ph9c table.bullet3, #article_body_unique .ph1d table.bullet3, #article_body_unique .ph2d table.bullet3, #article_body_unique .ph3d table.bullet3, #article_body_unique .ph4d table.bullet3, #article_body_unique .ph5d table.bullet3, #article_body_unique .ph6d table.bullet3, #article_body_unique .ph7d table.bullet3, #article_body_unique .ph8d table.bullet3, #article_body_unique .ph9d table.bullet3, #article_body_unique .ph1e table.bullet3, #article_body_unique .ph2e table.bullet3, #article_body_unique .ph3e table.bullet3, #article_body_unique .ph4e table.bullet3, #article_body_unique .ph5e table.bullet3, #article_body_unique .ph6e table.bullet3, #article_body_unique .ph7e table.bullet3, #article_body_unique .ph8e table.bullet3, #article_body_unique .ph9e table.bullet3, #article_body_unique .ph1f table.bullet3, #article_body_unique .ph2f table.bullet3, #article_body_unique .ph3f table.bullet3, #article_body_unique .ph4f table.bullet3, #article_body_unique .ph5f table.bullet3, #article_body_unique .ph6f table.bullet3, #article_body_unique .ph7f table.bullet3, #article_body_unique .ph8f table.bullet3, #article_body_unique .ph9f table.bullet3 {
  padding-left: 2.7em; }
#article_body_unique .b_c_padding_bottom table.bullet4, #article_body_unique .ph1b table.bullet4, #article_body_unique .ph2b table.bullet4, #article_body_unique .ph3b table.bullet4, #article_body_unique .ph4b table.bullet4, #article_body_unique .ph5b table.bullet4, #article_body_unique .ph6b table.bullet4, #article_body_unique .ph7b table.bullet4, #article_body_unique .ph8b table.bullet4, #article_body_unique .ph9b table.bullet4, #article_body_unique .ph1c table.bullet4, #article_body_unique .ph2c table.bullet4, #article_body_unique .ph3c table.bullet4, #article_body_unique .ph4c table.bullet4, #article_body_unique .ph5c table.bullet4, #article_body_unique .ph6c table.bullet4, #article_body_unique .ph7c table.bullet4, #article_body_unique .ph8c table.bullet4, #article_body_unique .ph9c table.bullet4, #article_body_unique .ph1d table.bullet4, #article_body_unique .ph2d table.bullet4, #article_body_unique .ph3d table.bullet4, #article_body_unique .ph4d table.bullet4, #article_body_unique .ph5d table.bullet4, #article_body_unique .ph6d table.bullet4, #article_body_unique .ph7d table.bullet4, #article_body_unique .ph8d table.bullet4, #article_body_unique .ph9d table.bullet4, #article_body_unique .ph1e table.bullet4, #article_body_unique .ph2e table.bullet4, #article_body_unique .ph3e table.bullet4, #article_body_unique .ph4e table.bullet4, #article_body_unique .ph5e table.bullet4, #article_body_unique .ph6e table.bullet4, #article_body_unique .ph7e table.bullet4, #article_body_unique .ph8e table.bullet4, #article_body_unique .ph9e table.bullet4, #article_body_unique .ph1f table.bullet4, #article_body_unique .ph2f table.bullet4, #article_body_unique .ph3f table.bullet4, #article_body_unique .ph4f table.bullet4, #article_body_unique .ph5f table.bullet4, #article_body_unique .ph6f table.bullet4, #article_body_unique .ph7f table.bullet4, #article_body_unique .ph8f table.bullet4, #article_body_unique .ph9f table.bullet4 {
  padding-left: 3.6em; }
#article_body_unique .b_c_padding_bottom .divbox .divbox_note_text p, #article_body_unique .b_c_padding_bottom .divbox .divbox_example_text p, #article_body_unique .b_c_padding_bottom .divbox .divbox_warning_text p, #article_body_unique .ph1b .divbox .divbox_note_text p, #article_body_unique .ph1b .divbox .divbox_example_text p, #article_body_unique .ph1b .divbox .divbox_warning_text p, #article_body_unique .ph2b .divbox .divbox_note_text p, #article_body_unique .ph2b .divbox .divbox_example_text p, #article_body_unique .ph2b .divbox .divbox_warning_text p, #article_body_unique .ph3b .divbox .divbox_note_text p, #article_body_unique .ph3b .divbox .divbox_example_text p, #article_body_unique .ph3b .divbox .divbox_warning_text p, #article_body_unique .ph4b .divbox .divbox_note_text p, #article_body_unique .ph4b .divbox .divbox_example_text p, #article_body_unique .ph4b .divbox .divbox_warning_text p, #article_body_unique .ph5b .divbox .divbox_note_text p, #article_body_unique .ph5b .divbox .divbox_example_text p, #article_body_unique .ph5b .divbox .divbox_warning_text p, #article_body_unique .ph6b .divbox .divbox_note_text p, #article_body_unique .ph6b .divbox .divbox_example_text p, #article_body_unique .ph6b .divbox .divbox_warning_text p, #article_body_unique .ph7b .divbox .divbox_note_text p, #article_body_unique .ph7b .divbox .divbox_example_text p, #article_body_unique .ph7b .divbox .divbox_warning_text p, #article_body_unique .ph8b .divbox .divbox_note_text p, #article_body_unique .ph8b .divbox .divbox_example_text p, #article_body_unique .ph8b .divbox .divbox_warning_text p, #article_body_unique .ph9b .divbox .divbox_note_text p, #article_body_unique .ph9b .divbox .divbox_example_text p, #article_body_unique .ph9b .divbox .divbox_warning_text p, #article_body_unique .ph1c .divbox .divbox_note_text p, #article_body_unique .ph1c .divbox .divbox_example_text p, #article_body_unique .ph1c .divbox .divbox_warning_text p, #article_body_unique .ph2c .divbox .divbox_note_text p, #article_body_unique .ph2c .divbox .divbox_example_text p, #article_body_unique .ph2c .divbox .divbox_warning_text p, #article_body_unique .ph3c .divbox .divbox_note_text p, #article_body_unique .ph3c .divbox .divbox_example_text p, #article_body_unique .ph3c .divbox .divbox_warning_text p, #article_body_unique .ph4c .divbox .divbox_note_text p, #article_body_unique .ph4c .divbox .divbox_example_text p, #article_body_unique .ph4c .divbox .divbox_warning_text p, #article_body_unique .ph5c .divbox .divbox_note_text p, #article_body_unique .ph5c .divbox .divbox_example_text p, #article_body_unique .ph5c .divbox .divbox_warning_text p, #article_body_unique .ph6c .divbox .divbox_note_text p, #article_body_unique .ph6c .divbox .divbox_example_text p, #article_body_unique .ph6c .divbox .divbox_warning_text p, #article_body_unique .ph7c .divbox .divbox_note_text p, #article_body_unique .ph7c .divbox .divbox_example_text p, #article_body_unique .ph7c .divbox .divbox_warning_text p, #article_body_unique .ph8c .divbox .divbox_note_text p, #article_body_unique .ph8c .divbox .divbox_example_text p, #article_body_unique .ph8c .divbox .divbox_warning_text p, #article_body_unique .ph9c .divbox .divbox_note_text p, #article_body_unique .ph9c .divbox .divbox_example_text p, #article_body_unique .ph9c .divbox .divbox_warning_text p, #article_body_unique .ph1d .divbox .divbox_note_text p, #article_body_unique .ph1d .divbox .divbox_example_text p, #article_body_unique .ph1d .divbox .divbox_warning_text p, #article_body_unique .ph2d .divbox .divbox_note_text p, #article_body_unique .ph2d .divbox .divbox_example_text p, #article_body_unique .ph2d .divbox .divbox_warning_text p, #article_body_unique .ph3d .divbox .divbox_note_text p, #article_body_unique .ph3d .divbox .divbox_example_text p, #article_body_unique .ph3d .divbox .divbox_warning_text p, #article_body_unique .ph4d .divbox .divbox_note_text p, #article_body_unique .ph4d .divbox .divbox_example_text p, #article_body_unique .ph4d .divbox .divbox_warning_text p, #article_body_unique .ph5d .divbox .divbox_note_text p, #article_body_unique .ph5d .divbox .divbox_example_text p, #article_body_unique .ph5d .divbox .divbox_warning_text p, #article_body_unique .ph6d .divbox .divbox_note_text p, #article_body_unique .ph6d .divbox .divbox_example_text p, #article_body_unique .ph6d .divbox .divbox_warning_text p, #article_body_unique .ph7d .divbox .divbox_note_text p, #article_body_unique .ph7d .divbox .divbox_example_text p, #article_body_unique .ph7d .divbox .divbox_warning_text p, #article_body_unique .ph8d .divbox .divbox_note_text p, #article_body_unique .ph8d .divbox .divbox_example_text p, #article_body_unique .ph8d .divbox .divbox_warning_text p, #article_body_unique .ph9d .divbox .divbox_note_text p, #article_body_unique .ph9d .divbox .divbox_example_text p, #article_body_unique .ph9d .divbox .divbox_warning_text p, #article_body_unique .ph1e .divbox .divbox_note_text p, #article_body_unique .ph1e .divbox .divbox_example_text p, #article_body_unique .ph1e .divbox .divbox_warning_text p, #article_body_unique .ph2e .divbox .divbox_note_text p, #article_body_unique .ph2e .divbox .divbox_example_text p, #article_body_unique .ph2e .divbox .divbox_warning_text p, #article_body_unique .ph3e .divbox .divbox_note_text p, #article_body_unique .ph3e .divbox .divbox_example_text p, #article_body_unique .ph3e .divbox .divbox_warning_text p, #article_body_unique .ph4e .divbox .divbox_note_text p, #article_body_unique .ph4e .divbox .divbox_example_text p, #article_body_unique .ph4e .divbox .divbox_warning_text p, #article_body_unique .ph5e .divbox .divbox_note_text p, #article_body_unique .ph5e .divbox .divbox_example_text p, #article_body_unique .ph5e .divbox .divbox_warning_text p, #article_body_unique .ph6e .divbox .divbox_note_text p, #article_body_unique .ph6e .divbox .divbox_example_text p, #article_body_unique .ph6e .divbox .divbox_warning_text p, #article_body_unique .ph7e .divbox .divbox_note_text p, #article_body_unique .ph7e .divbox .divbox_example_text p, #article_body_unique .ph7e .divbox .divbox_warning_text p, #article_body_unique .ph8e .divbox .divbox_note_text p, #article_body_unique .ph8e .divbox .divbox_example_text p, #article_body_unique .ph8e .divbox .divbox_warning_text p, #article_body_unique .ph9e .divbox .divbox_note_text p, #article_body_unique .ph9e .divbox .divbox_example_text p, #article_body_unique .ph9e .divbox .divbox_warning_text p, #article_body_unique .ph1f .divbox .divbox_note_text p, #article_body_unique .ph1f .divbox .divbox_example_text p, #article_body_unique .ph1f .divbox .divbox_warning_text p, #article_body_unique .ph2f .divbox .divbox_note_text p, #article_body_unique .ph2f .divbox .divbox_example_text p, #article_body_unique .ph2f .divbox .divbox_warning_text p, #article_body_unique .ph3f .divbox .divbox_note_text p, #article_body_unique .ph3f .divbox .divbox_example_text p, #article_body_unique .ph3f .divbox .divbox_warning_text p, #article_body_unique .ph4f .divbox .divbox_note_text p, #article_body_unique .ph4f .divbox .divbox_example_text p, #article_body_unique .ph4f .divbox .divbox_warning_text p, #article_body_unique .ph5f .divbox .divbox_note_text p, #article_body_unique .ph5f .divbox .divbox_example_text p, #article_body_unique .ph5f .divbox .divbox_warning_text p, #article_body_unique .ph6f .divbox .divbox_note_text p, #article_body_unique .ph6f .divbox .divbox_example_text p, #article_body_unique .ph6f .divbox .divbox_warning_text p, #article_body_unique .ph7f .divbox .divbox_note_text p, #article_body_unique .ph7f .divbox .divbox_example_text p, #article_body_unique .ph7f .divbox .divbox_warning_text p, #article_body_unique .ph8f .divbox .divbox_note_text p, #article_body_unique .ph8f .divbox .divbox_example_text p, #article_body_unique .ph8f .divbox .divbox_warning_text p, #article_body_unique .ph9f .divbox .divbox_note_text p, #article_body_unique .ph9f .divbox .divbox_example_text p, #article_body_unique .ph9f .divbox .divbox_warning_text p {
  padding-left: 5px; }
#article_body_unique .b_c_padding_bottom .divbox .divbox_note_text table.bullet, #article_body_unique .b_c_padding_bottom .divbox .divbox_example_text table.bullet, #article_body_unique .b_c_padding_bottom .divbox .divbox_warning_text table.bullet, #article_body_unique .ph1b .divbox .divbox_note_text table.bullet, #article_body_unique .ph1b .divbox .divbox_example_text table.bullet, #article_body_unique .ph1b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph2b .divbox .divbox_note_text table.bullet, #article_body_unique .ph2b .divbox .divbox_example_text table.bullet, #article_body_unique .ph2b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph3b .divbox .divbox_note_text table.bullet, #article_body_unique .ph3b .divbox .divbox_example_text table.bullet, #article_body_unique .ph3b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph4b .divbox .divbox_note_text table.bullet, #article_body_unique .ph4b .divbox .divbox_example_text table.bullet, #article_body_unique .ph4b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph5b .divbox .divbox_note_text table.bullet, #article_body_unique .ph5b .divbox .divbox_example_text table.bullet, #article_body_unique .ph5b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph6b .divbox .divbox_note_text table.bullet, #article_body_unique .ph6b .divbox .divbox_example_text table.bullet, #article_body_unique .ph6b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph7b .divbox .divbox_note_text table.bullet, #article_body_unique .ph7b .divbox .divbox_example_text table.bullet, #article_body_unique .ph7b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph8b .divbox .divbox_note_text table.bullet, #article_body_unique .ph8b .divbox .divbox_example_text table.bullet, #article_body_unique .ph8b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph9b .divbox .divbox_note_text table.bullet, #article_body_unique .ph9b .divbox .divbox_example_text table.bullet, #article_body_unique .ph9b .divbox .divbox_warning_text table.bullet, #article_body_unique .ph1c .divbox .divbox_note_text table.bullet, #article_body_unique .ph1c .divbox .divbox_example_text table.bullet, #article_body_unique .ph1c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph2c .divbox .divbox_note_text table.bullet, #article_body_unique .ph2c .divbox .divbox_example_text table.bullet, #article_body_unique .ph2c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph3c .divbox .divbox_note_text table.bullet, #article_body_unique .ph3c .divbox .divbox_example_text table.bullet, #article_body_unique .ph3c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph4c .divbox .divbox_note_text table.bullet, #article_body_unique .ph4c .divbox .divbox_example_text table.bullet, #article_body_unique .ph4c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph5c .divbox .divbox_note_text table.bullet, #article_body_unique .ph5c .divbox .divbox_example_text table.bullet, #article_body_unique .ph5c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph6c .divbox .divbox_note_text table.bullet, #article_body_unique .ph6c .divbox .divbox_example_text table.bullet, #article_body_unique .ph6c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph7c .divbox .divbox_note_text table.bullet, #article_body_unique .ph7c .divbox .divbox_example_text table.bullet, #article_body_unique .ph7c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph8c .divbox .divbox_note_text table.bullet, #article_body_unique .ph8c .divbox .divbox_example_text table.bullet, #article_body_unique .ph8c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph9c .divbox .divbox_note_text table.bullet, #article_body_unique .ph9c .divbox .divbox_example_text table.bullet, #article_body_unique .ph9c .divbox .divbox_warning_text table.bullet, #article_body_unique .ph1d .divbox .divbox_note_text table.bullet, #article_body_unique .ph1d .divbox .divbox_example_text table.bullet, #article_body_unique .ph1d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph2d .divbox .divbox_note_text table.bullet, #article_body_unique .ph2d .divbox .divbox_example_text table.bullet, #article_body_unique .ph2d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph3d .divbox .divbox_note_text table.bullet, #article_body_unique .ph3d .divbox .divbox_example_text table.bullet, #article_body_unique .ph3d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph4d .divbox .divbox_note_text table.bullet, #article_body_unique .ph4d .divbox .divbox_example_text table.bullet, #article_body_unique .ph4d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph5d .divbox .divbox_note_text table.bullet, #article_body_unique .ph5d .divbox .divbox_example_text table.bullet, #article_body_unique .ph5d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph6d .divbox .divbox_note_text table.bullet, #article_body_unique .ph6d .divbox .divbox_example_text table.bullet, #article_body_unique .ph6d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph7d .divbox .divbox_note_text table.bullet, #article_body_unique .ph7d .divbox .divbox_example_text table.bullet, #article_body_unique .ph7d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph8d .divbox .divbox_note_text table.bullet, #article_body_unique .ph8d .divbox .divbox_example_text table.bullet, #article_body_unique .ph8d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph9d .divbox .divbox_note_text table.bullet, #article_body_unique .ph9d .divbox .divbox_example_text table.bullet, #article_body_unique .ph9d .divbox .divbox_warning_text table.bullet, #article_body_unique .ph1e .divbox .divbox_note_text table.bullet, #article_body_unique .ph1e .divbox .divbox_example_text table.bullet, #article_body_unique .ph1e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph2e .divbox .divbox_note_text table.bullet, #article_body_unique .ph2e .divbox .divbox_example_text table.bullet, #article_body_unique .ph2e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph3e .divbox .divbox_note_text table.bullet, #article_body_unique .ph3e .divbox .divbox_example_text table.bullet, #article_body_unique .ph3e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph4e .divbox .divbox_note_text table.bullet, #article_body_unique .ph4e .divbox .divbox_example_text table.bullet, #article_body_unique .ph4e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph5e .divbox .divbox_note_text table.bullet, #article_body_unique .ph5e .divbox .divbox_example_text table.bullet, #article_body_unique .ph5e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph6e .divbox .divbox_note_text table.bullet, #article_body_unique .ph6e .divbox .divbox_example_text table.bullet, #article_body_unique .ph6e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph7e .divbox .divbox_note_text table.bullet, #article_body_unique .ph7e .divbox .divbox_example_text table.bullet, #article_body_unique .ph7e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph8e .divbox .divbox_note_text table.bullet, #article_body_unique .ph8e .divbox .divbox_example_text table.bullet, #article_body_unique .ph8e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph9e .divbox .divbox_note_text table.bullet, #article_body_unique .ph9e .divbox .divbox_example_text table.bullet, #article_body_unique .ph9e .divbox .divbox_warning_text table.bullet, #article_body_unique .ph1f .divbox .divbox_note_text table.bullet, #article_body_unique .ph1f .divbox .divbox_example_text table.bullet, #article_body_unique .ph1f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph2f .divbox .divbox_note_text table.bullet, #article_body_unique .ph2f .divbox .divbox_example_text table.bullet, #article_body_unique .ph2f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph3f .divbox .divbox_note_text table.bullet, #article_body_unique .ph3f .divbox .divbox_example_text table.bullet, #article_body_unique .ph3f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph4f .divbox .divbox_note_text table.bullet, #article_body_unique .ph4f .divbox .divbox_example_text table.bullet, #article_body_unique .ph4f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph5f .divbox .divbox_note_text table.bullet, #article_body_unique .ph5f .divbox .divbox_example_text table.bullet, #article_body_unique .ph5f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph6f .divbox .divbox_note_text table.bullet, #article_body_unique .ph6f .divbox .divbox_example_text table.bullet, #article_body_unique .ph6f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph7f .divbox .divbox_note_text table.bullet, #article_body_unique .ph7f .divbox .divbox_example_text table.bullet, #article_body_unique .ph7f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph8f .divbox .divbox_note_text table.bullet, #article_body_unique .ph8f .divbox .divbox_example_text table.bullet, #article_body_unique .ph8f .divbox .divbox_warning_text table.bullet, #article_body_unique .ph9f .divbox .divbox_note_text table.bullet, #article_body_unique .ph9f .divbox .divbox_example_text table.bullet, #article_body_unique .ph9f .divbox .divbox_warning_text table.bullet {
  padding-left: 0.9em; }
#article_body_unique .b_c_padding_bottom .divbox .divbox_note_text table.bullet2, #article_body_unique .b_c_padding_bottom .divbox .divbox_example_text table.bullet2, #article_body_unique .b_c_padding_bottom .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph1b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph1b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph1b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph2b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph2b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph2b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph3b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph3b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph3b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph4b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph4b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph4b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph5b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph5b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph5b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph6b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph6b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph6b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph7b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph7b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph7b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph8b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph8b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph8b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph9b .divbox .divbox_note_text table.bullet2, #article_body_unique .ph9b .divbox .divbox_example_text table.bullet2, #article_body_unique .ph9b .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph1c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph1c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph1c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph2c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph2c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph2c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph3c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph3c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph3c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph4c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph4c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph4c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph5c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph5c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph5c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph6c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph6c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph6c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph7c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph7c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph7c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph8c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph8c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph8c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph9c .divbox .divbox_note_text table.bullet2, #article_body_unique .ph9c .divbox .divbox_example_text table.bullet2, #article_body_unique .ph9c .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph1d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph1d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph1d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph2d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph2d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph2d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph3d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph3d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph3d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph4d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph4d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph4d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph5d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph5d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph5d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph6d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph6d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph6d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph7d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph7d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph7d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph8d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph8d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph8d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph9d .divbox .divbox_note_text table.bullet2, #article_body_unique .ph9d .divbox .divbox_example_text table.bullet2, #article_body_unique .ph9d .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph1e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph1e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph1e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph2e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph2e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph2e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph3e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph3e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph3e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph4e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph4e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph4e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph5e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph5e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph5e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph6e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph6e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph6e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph7e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph7e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph7e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph8e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph8e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph8e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph9e .divbox .divbox_note_text table.bullet2, #article_body_unique .ph9e .divbox .divbox_example_text table.bullet2, #article_body_unique .ph9e .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph1f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph1f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph1f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph2f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph2f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph2f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph3f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph3f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph3f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph4f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph4f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph4f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph5f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph5f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph5f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph6f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph6f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph6f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph7f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph7f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph7f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph8f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph8f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph8f .divbox .divbox_warning_text table.bullet2, #article_body_unique .ph9f .divbox .divbox_note_text table.bullet2, #article_body_unique .ph9f .divbox .divbox_example_text table.bullet2, #article_body_unique .ph9f .divbox .divbox_warning_text table.bullet2 {
  padding-left: 1.8em; }
#article_body_unique .b_c_padding_bottom .divbox .divbox_note_text table.bullet3, #article_body_unique .b_c_padding_bottom .divbox .divbox_example_text table.bullet3, #article_body_unique .b_c_padding_bottom .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph1b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph1b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph1b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph2b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph2b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph2b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph3b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph3b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph3b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph4b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph4b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph4b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph5b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph5b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph5b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph6b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph6b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph6b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph7b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph7b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph7b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph8b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph8b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph8b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph9b .divbox .divbox_note_text table.bullet3, #article_body_unique .ph9b .divbox .divbox_example_text table.bullet3, #article_body_unique .ph9b .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph1c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph1c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph1c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph2c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph2c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph2c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph3c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph3c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph3c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph4c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph4c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph4c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph5c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph5c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph5c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph6c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph6c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph6c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph7c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph7c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph7c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph8c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph8c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph8c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph9c .divbox .divbox_note_text table.bullet3, #article_body_unique .ph9c .divbox .divbox_example_text table.bullet3, #article_body_unique .ph9c .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph1d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph1d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph1d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph2d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph2d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph2d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph3d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph3d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph3d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph4d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph4d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph4d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph5d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph5d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph5d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph6d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph6d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph6d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph7d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph7d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph7d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph8d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph8d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph8d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph9d .divbox .divbox_note_text table.bullet3, #article_body_unique .ph9d .divbox .divbox_example_text table.bullet3, #article_body_unique .ph9d .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph1e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph1e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph1e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph2e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph2e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph2e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph3e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph3e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph3e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph4e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph4e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph4e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph5e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph5e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph5e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph6e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph6e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph6e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph7e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph7e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph7e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph8e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph8e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph8e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph9e .divbox .divbox_note_text table.bullet3, #article_body_unique .ph9e .divbox .divbox_example_text table.bullet3, #article_body_unique .ph9e .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph1f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph1f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph1f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph2f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph2f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph2f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph3f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph3f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph3f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph4f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph4f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph4f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph5f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph5f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph5f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph6f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph6f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph6f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph7f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph7f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph7f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph8f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph8f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph8f .divbox .divbox_warning_text table.bullet3, #article_body_unique .ph9f .divbox .divbox_note_text table.bullet3, #article_body_unique .ph9f .divbox .divbox_example_text table.bullet3, #article_body_unique .ph9f .divbox .divbox_warning_text table.bullet3 {
  padding-left: 2.7em; }
#article_body_unique .b_c_padding_bottom .divbox .divbox_note_text table.bullet4, #article_body_unique .b_c_padding_bottom .divbox .divbox_example_text table.bullet4, #article_body_unique .b_c_padding_bottom .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph1b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph1b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph1b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph2b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph2b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph2b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph3b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph3b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph3b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph4b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph4b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph4b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph5b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph5b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph5b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph6b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph6b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph6b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph7b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph7b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph7b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph8b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph8b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph8b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph9b .divbox .divbox_note_text table.bullet4, #article_body_unique .ph9b .divbox .divbox_example_text table.bullet4, #article_body_unique .ph9b .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph1c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph1c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph1c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph2c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph2c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph2c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph3c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph3c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph3c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph4c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph4c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph4c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph5c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph5c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph5c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph6c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph6c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph6c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph7c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph7c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph7c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph8c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph8c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph8c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph9c .divbox .divbox_note_text table.bullet4, #article_body_unique .ph9c .divbox .divbox_example_text table.bullet4, #article_body_unique .ph9c .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph1d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph1d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph1d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph2d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph2d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph2d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph3d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph3d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph3d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph4d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph4d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph4d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph5d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph5d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph5d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph6d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph6d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph6d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph7d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph7d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph7d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph8d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph8d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph8d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph9d .divbox .divbox_note_text table.bullet4, #article_body_unique .ph9d .divbox .divbox_example_text table.bullet4, #article_body_unique .ph9d .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph1e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph1e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph1e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph2e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph2e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph2e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph3e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph3e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph3e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph4e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph4e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph4e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph5e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph5e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph5e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph6e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph6e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph6e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph7e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph7e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph7e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph8e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph8e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph8e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph9e .divbox .divbox_note_text table.bullet4, #article_body_unique .ph9e .divbox .divbox_example_text table.bullet4, #article_body_unique .ph9e .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph1f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph1f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph1f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph2f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph2f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph2f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph3f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph3f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph3f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph4f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph4f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph4f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph5f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph5f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph5f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph6f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph6f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph6f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph7f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph7f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph7f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph8f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph8f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph8f .divbox .divbox_warning_text table.bullet4, #article_body_unique .ph9f .divbox .divbox_note_text table.bullet4, #article_body_unique .ph9f .divbox .divbox_example_text table.bullet4, #article_body_unique .ph9f .divbox .divbox_warning_text table.bullet4 {
  padding-left: 3.6em; }

table.bullet, table.bullet2, table.bullet3, table.bullet4 {
  margin: 0; }
  table.bullet tbody tr td.point, table.bullet tbody tr td.point_small,   table.bullet2 tbody tr td.point, table.bullet2 tbody tr td.point_small,   table.bullet3 tbody tr td.point, table.bullet3 tbody tr td.point_small,   table.bullet4 tbody tr td.point, table.bullet4 tbody tr td.point_small {
    vertical-align: top;
    font-family: 'dejavu sans mono', 'times new roman', sans-serif; }
  table.bullet tbody tr td.point_small,   table.bullet2 tbody tr td.point_small,   table.bullet3 tbody tr td.point_small,   table.bullet4 tbody tr td.point_small {
    font-size: 0.7em;
    padding-top: 2px; }
  table.bullet tbody tr td.point_number,   table.bullet2 tbody tr td.point_number,   table.bullet3 tbody tr td.point_number,   table.bullet4 tbody tr td.point_number {
    vertical-align: top; }
  table.bullet tbody tr td.text,   table.bullet2 tbody tr td.text,   table.bullet3 tbody tr td.text,   table.bullet4 tbody tr td.text {
    padding-left: 5px;
    line-spacing: 95%; }

Can you imagine doing this in plain CSS? Here is the SASS for the corresponding section:

#article_body_unique
  .b_c_padding_bottom, .ph1b, .ph2b, .ph3b, .ph4b, .ph5b, .ph6b, .ph7b, .ph8b, .ph9b, .ph1c, .ph2c, .ph3c, .ph4c, .ph5c, .ph6c, .ph7c, .ph8c, .ph9c, .ph1d, .ph2d, .ph3d, .ph4d, .ph5d, .ph6d, .ph7d, .ph8d, .ph9d, .ph1e, .ph2e, .ph3e, .ph4e, .ph5e, .ph6e, .ph7e, .ph8e, .ph9e, .ph1f, .ph2f, .ph3f, .ph4f, .ph5f, .ph6f, .ph7f, .ph8f, .ph9f
    table.bullet
      :padding-left = !padding_left_outline_base * 1
    table.bullet2
      :padding-left = !padding_left_outline_base * 2
    table.bullet3
      :padding-left = !padding_left_outline_base * 3
    table.bullet4
      :padding-left = !padding_left_outline_base * 4
    .divbox
      .divbox_note_text, .divbox_example_text, .divbox_warning_text
        p
          :padding-left 5px
        table.bullet
          :padding-left = !padding_left_outline_base * 1
        table.bullet2
          :padding-left = !padding_left_outline_base * 2
        table.bullet3
          :padding-left = !padding_left_outline_base * 3
        table.bullet4
          :padding-left = !padding_left_outline_base * 4

table.bullet, table.bullet2, table.bullet3, table.bullet4
  :margin 0
  //:font-size 90%
  tbody
    tr
      td.point, td.point_small
        :vertical-align top
        :font-family = !font_constant
      td.point_small
        :font-size 0.7em
        :padding-top 2px
      td.point_number
        :vertical-align top
      td.text
        :padding-left 5px
        :line-spacing 95%

So use SASS, and explore new ways to structure your CSS files. And once your stylesheet theme is set in stone, you can make SASS generate all the CSS code into a single line – effectively reducing bandwidth usage, and also acting as a poor man’s way of obfuscating brilliant CSS ideas.

My Favorite Firefox theme “rein”

Filed under: FYI — Tags: — Shinobu @ 10:49 am

It’s called rein you can get it here. Mind you, I just switched today after using Whitehart for about ~5 years.

Chromifox looks very good too, but it’s not original. Plus, it doesn’t integrate well with the Aurora GTK engine/theme.

Here is a screenshot of rein in action on my Xmonad + Vimperator setup (with Terminus as the GUI font, of course).

firefox (w/ vimperator) on Xmonad + "rein" firefox theme

firefox (w/ vimperator) on Xmonad + "rein" firefox theme

You gotta love those tabs. Finally, a theme that looks clean, simple, and unique.

January 17, 2009

How to quickly make a playlist for mplayer

Filed under: FYI, Linux, Music — Shinobu @ 11:37 pm

Mplayer uses a simple kind of playlist: a text file with the path and name of each file to be played. The path to the new file is relative to the location of the playlist file itself. So, you can do something like this:

find -maxdepth 1 -type f -name \*.\* > playlist

This will find all the files in the current directory that have a “.” character in it, and put the results into playlist (a text file) — i.e., it will find all files with some kind of extension, and exclude directory names with a period in them. This works well if the only type of files with extensions are audio files. If you want to search deeper down directory levels, just increase the maxdepth value, or leave out the maxdepth parameter altogether to search recursively.

The “>” operator replaces whatever text was inside the “playlist” file with the output of the previous command (here, the find command with all our options). If you just wanted to append the results to an existing playlist file, you could just use “>>” instead of “>”.

To play the playlist, just do:

mplayer -playlist playlist

…where “playlist” is the file with all the songs in it. Be sure to include the full path to the playlist if you are currently not inside the same directory. To make the entire playlist loop forever, type:

mplayer -playlist playlist -loop 0

and it will loop the entire playlist forever. Unfortunately, putting the “loop=0″ info in my ~/.mplayer/config file makes mplayer read that paramter first, and thus, only repeat the first file in my playlist forever. There seems to be no workaroud to this, except manually appending the loop paramter after the playlist parameter, as shown above.

More info here.

UPDATE November 12, 2009: I discovered a simple hack around the above mentioned problem about trying to loop the entire playlist. The solution is to remove the “loop=0″ line from your ~/.mplayer/config, and instead make use of shell aliases. I use zsh, and this is what I have in my ~/.zshrc (the second alias is the key):

alias m='mplayer -loop 0'
alias mp='mplayer -loop 0 -playlist'

Now, to play any single file infinitely, simply use “m [file]“. To infinitely loop an entire playlist, simply do “mp [playlist]“. You can “>” and “<” hotkeys to move around the playlist.

Older Posts »

Blog at WordPress.com.