Hearing Sound from Firefox Using Bluetooth Headphones in FreeBSD

I’ve gotten myself Bluetooth Headphones and a USB Bluetooth dongles, and I want to hear sounds through my new headphones.

Since the headphones are a Bluetooth device, they should be discovered and paired. In the famous manual, FreeBSD Handbook , there are two sections in which to find instructions on Bluetooth and sound:

  • 33.5 Bluetooth – in chapter 33 – Advanced Networking.
    There is also a useful utility named bluetooth-config you can use to create or modify the files ‘/etc/bluetooth/hcsecd.conf.; and ‘/etc/bluetooth/hosts
  • 8.2.3. Setting up Bluetooth Sound Devices – in chapter 8 – Multimedia

Having configured Bluetooth and installed virtual_oss. All you have to do each time you want to listen through your Bluetooth headphones is to run the following commands replacing BT_ADDR by your device name:

  1. hccontrol -n ubt0hci create_onnection BT_ADDR
  2. virtual_oss -C 2 -c 2 -r 48000 -b 16 -s 768 -R /dev/null -P /dev/bluetooth/BT_ADDR -d dsp

Now, if you use VLC to listen to audio, all you have to do is select the ‘dsp’ output device. But, if you want to hear the sounds plyed by Firefox, you should have to add a module to PulseAudio. I haven’t found any Bluetooth modules I can install on my FreeBSD, but have found that module-sndio can do the job for me,, to add it, run the command:

pkg install pulseaudio-module-sndio

And add the following line to ‘/usr/local/etc/pulse/default.pa

load-module module-sndio device=snd/0

To start the service sndio at boot time, add the following line to ‘/etc/rc.conf‘:

sndiod_enable="YES"

To hear sounds from the Firefox browser, make sure PulseAudio stream it to ‘/snd/0‘ My display manager is XFCE4, and I use the plugin ‘xfce4-pulseaudio-plugin’ to view my output devices. In the following image, you can see that firefox sounds are streamed to that device:

Now, if everythiing is set correctly, but you cannot hear the sound, type the follwing shell command as a regular user:

pulseaudio --kill
Advertisement

Firefox Add-on for Downloading the Right Version of Software

The other day, I was invited to a zoom meeting. Zoom is a video conference application also available for computers. It’s address is https://zoom.us.

When the time of our meeting came, I couldn’t hear anything when connecting from my Firefox browser, and saw the following message:

.

After a short IRC conversation on #freebsd@freenode.org, I installed the User-Agent Switcher and Manager add-on on my Firefox.

This add-on adds an icon to the toolbar, Following is the icon as seen in the dark theme:

Now, when you click the icon, you will see the following popup:

Great! Now you can select a browser and operating system using the drop down lists, and then select the browser’s version using one of the radio button. Then, click the “Apply” button to save your changes and enable the add-on. Click the “Test” button to see what browser details will be passed to the remote server.

Good luck!

Overcoming PDF Problems With Firefox

enter image description here

The other day I downloaded “Fahrenheit 451” by Ray Bradbury as a free eBook, and tried to read it. I found that I cannot read much more than the titles of each chapter.

enter image description here
enter image description here

I tried double-clicking and dragging, and saw that something appears on the screen, organized in paragraphs.

Right Click->Inspect Element

enter image description here
enter image description here
enter image description here

Now, a sub-window is opened at the bottom of the screen:

You can see in that sub-window that some text in English appears in a ‘div’ element just under another ‘div’ element of class ‘textLayer’. To the right of the ‘Inspect Element’ sub-window you can see the CSS rules:

As you can see, the value of property ‘color’ is ‘transparent’, You can edit that property using the color selector or by overriding the text value.
Let’s set it to ‘black’.

Now, you can see the paragraphs.
You can change the opacity property of ‘div.textLayer’ from 0.2 to a higher value (up to 1) in order to read the text better.
Firefox is a great PDF viewer, but my browser couldn’t save the document with the changes: the result was a corrupt file that cannot be opened. I’d written about it to the newsgroup ‘mozilla.wishlist’ found on server ‘news.mozilla.org’. and they opened a ticket.

CSS Animations (Without Javascript)

CSS3 is the newest CSS standard, and is supported by all modern browsers. Among the new style properties supported in CSS3, there are animation properties. Those properties allows you to animate HTML elements without the need of Javascript. CSS3 allows more animation options than those done by the non-standard yet supported marquee tags. It also allows gradual changes of font sizes, colors, rotation angles, etc.

To make an element or a group of elements (defined by a selector) animated, add animation properties to its selector’s property block. For multi-browser support, writing each animation property twice – once with the prefix ‘-webkit-‘ and once without – is recommended.

In addition, you should add two animation rules: “@keyframes” and “@-webkit-keyframes” to describe the animated changes of elements.

NOTE: Chrome, Safari & Opera require the ‘-webkit-‘ prefix` Firefox and Explorer 10+ do not.

Animation Attributes

For my own convenience, please allow me to drop the ‘-webkit-‘ prefix from the following attribute names:

  • animation: animation-name duration;
  • animation-iteration-count: number-of-iterations;
    number-of-iterations may be an integer or “infinite”
  • animation-direction: direction.
    direction of change, not only left-to-right or top-to-bottom, but also, for example, from onecolor to another. the values for this property can be: normal, reverse, alternate, alternate-reverse, initial, or inherit,
  • animation-timing-function: function
    Function can be: linear, ease, cubic-bezier, etc. Read more here.

Here’s a little code example:

      div {
        position: relative;
        overflow: hidden;
        /* Chrome, Safari, Opera: with the prefix '-webkit-', others without. */
        -webkit-animation: myfirst 10s; 
        animation: myfirst 10s;
        -webkit-animation-iteration-count: infinite;
        animation-iteration-count: infinite;
        -webkit-animation-direction: normal;
        animation-direction: normal;
        -webkit-animation-timing-function: linear;
        animation-timing-function: linear;
      }

Read more about animation properties here.

Key Frame Rules

A key frame rule describes the gradually changed values at each key frame. The key frame value can be ‘from’, ‘to’ or the percentage of progress.

The syntax is:

@[-webkit-]keyframes animation-name {
   keyframe-value: {property-list}
   .
   .
   .
}

Here’s a little code example:

      /* Chrome, Safari, Opera */
        @-webkit-keyframes myfirst {
        from {color: red; font-size: 12px; left: 0px;}
        to {color: black; font-size: 48px; left: 100%; transform: rotate(-90deg)}

      }

      /* Standard syntax */
      @keyframes myfirst {
        from {color: red; font-size: 12px; left: 0px; }
        to {color: black; font-size: 48px; left: 100%; transform: rotate(-90deg);}
      } 

Read more about key frames here.

How To Develop Firefox Extensions – Files And Directories (Actually Coding It)

In the previous post, How To Develop Firefox Extensions – Intro, we discussed the Chrome document’s DOM. In this post, we’ll learn how to create an add-on that can be installed.  In this post, we’ll learn how to access the Chrome document’s nodes, and to organize an XPI (Cross Platform Installer) file.

XPI files are ZIP files

A file having an ‘.xpi’ suffix, is a compressed file in ‘.zip’ format. If we use Firefox as the opening program for those files, it will install an extension. We can refer to a zipped file as a root directory, containing files and sub-directories.

Following is a recommended directory structure:

  • /
    • install.rdf
    • chrome.manifest
    • content/
      • <filename>.xul
      • <filename>.js
    • locale/
      • <language code>/
        • <filename>.dtd
      • <language code>/
        • <filename>.dtd
      • .
      • .
      • .
    • skin/
      • <filename>.css

The XUL File

The XUL file is located in the content directory. XUL is an acronym for *XML User-interface Language’. The XUL file is a data file that makes the development of Mozilla extensions easier. The following example is an Overlay XUL file, i.e. an XUL used for adding a component to the browser’s Chrome, the great UI container.

<?xml version="1.0"?>
<!DOCTYPE overlay SYSTEM
  "chrome://imageinnewtab_extension/locale/browserOverlay.dtd">

<overlay id="imageinnewtabextensionOverlay"
         xmlns:html="http://www.w3.org/1999/xhtml"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

 <script src="imageinnewtab_extension.js">
 </script>

    <menupopup id="contentAreaContextMenu"  >
        <menuitem id="context-imageinnewtab"
                  label="&phpandmoreimageinnewtab.image-new-tab.label;"
                  oncommand="ImageInNewTab.BrowserOverlay.openInNewTab(event)"
                  insertafter="context-viewimage"
                  hidden="true"
                 />
    </menupopup>

</overlay>

This overlay contains the required data for adding an “Open Image In New Tab” option to the context-menu that pops up when you right-click in the HTML document area. This file contains a link to a script and instructions to add a new menu item to the popup menu with the unique id ‘contentAreaContextMenu’.

Note that the value of the label attributes begins with an ampersand(‘&’) and ends with a seni-colons; this means that the value is variable. The actual value is translated according to the definitions found in the DTD file specified in the ‘!DOCTYPE’ tag.

The ‘oncommand’ attribute defines how Firefox should response to command events, i.e. the function called when the menu item is selected either by a mouse click or by a keyboard shortcut.

Learn more about XUL here.

The Javascript file

In this example, ‘content/imageinnewtab_extension.js’, the Javascript file, defines an object that response to the ‘command’ event. The object is initialized as a response to the “load” event, i.e. after the UI components has completed loading. When the Chrome document has completed loading, the new menu item is defined. The ‘init’ member is a function that defines what callback function to call when the context menu pops up.

Following is the code:

if ("undefined" == typeof(ImageInNewTab)) {
  var ImageInNewTab = {};
};

ImageInNewTab.BrowserOverlay = {
    hideIfNoImage: function(event){
      var element=document.popupNode;
      var whatWasClicked = document.getElementById("context-imageinnewtab");
      whatWasClicked.hidden = !(element instanceof Components.interfaces.nsIImageLoadingContent &&
                 element.currentURI);
    },

    init: function (event){
        var contextMenu = document.getElementById("contentAreaContextMenu");
        contextMenu.addEventListener("popupshowing", ImageInNewTab.BrowserOverlay.hideIfNoImage, false);
    },

    openInNewTab: function (event){
      gBrowser.addTab(document.popupNode.src);
    }

}

addEventListener("load",
                 ImageInNewTab.BrowserOverlay.init,false);

The Install RDF file

The ‘install.rdf’ file includes information for the browser. The information includes information shown to the installing end-uder, and for the browser to know if the extension supports the current browser version.

Following is an example:

<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
    <Description about="urn:mozilla:install-manifest">
        <em:id>imageinnewtab_extension@phpandmore.net</em:id>
        <em:name>Image in New Tab</em:name>
        <em:version>0.1</em:version>
        <em:description>Add a new Menu Item in the context menu to view an image in a new tab.</em:description>
        <em:creator>Amit Yaron</em:creator>
        <em:homepageURL>https://phpandmore.net/</em:homepageURL>
        <em:type>2</em:type> <!-- type=extension --> 

        <em:targetApplication>
           <!-- Firefox -->
           <Description>
                <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                <em:minVersion>3.5</em:minVersion>
                <!-- Since Firefox's numbering scheme is unpredictable, users
                are encouraged to edit this field to the current max value.
                -->
                <em:maxVersion>999.0.*</em:maxVersion>
           </Description>
        </em:targetApplication>
    </Description>
</RDF>

Note: don’t change the ’em:id’ tag value.

Learn more about the install.rdf here.

The Chrome Manifest

The ‘chrrome.manifest’ file is a simple text files that contains instructions on how to access Chrome URL addresses (beginning with ‘chrome://’.

Following is an example manifest:

content imageinnewtab_extension content/
skin imageinnewtab_extension classic/1.0 skin/
locale imageinnewtab_extension en-US locale/en-US/
locale imageinnewtab_extension he-IL locale/he-IL/

overlay chrome://browser/content/browser.xul chrome://imageinnewtab_extension/content/imageinnewtab_extension_overlay.xul
  • The ‘content ‘ instruction tells Firefox where to find ‘chrome://imageinnewtab_extension/content’, where the XUL and code are found.
  • The ‘skin ‘ instruction tells Firefox where to find ‘chrome://imageinnewtab_extension/skin’, where the CSS files are found.
  • The ‘locale ‘ instruction tells Firefox where to find ‘chrome://imageinnewtab_extension/locale’ according to the ‘LANG’ environment variable, This is where the DTD file, used for label translation, is found.
  • The ‘overlay’ instruction tells Firefox the role of the overlay XUL file, which extends the great UI container.

Learn more about the manifest here.

The Example Add-on

The example add-on, that opens an image in a new tab, can be downloaded here.

How To Develop a Firefox Extension – Intro

Firefox users can add functionality to their browser by installing an add-on.  To install an add-n click on Tools->Add-ons.

Add On

You can then search for your requested add-on: add-on to download movies from a site, to share a page in Facebook, to add a Delicious bookmark, etc. Another useful add-on is DOM Inspector, which allows you to locate and modify document elements. Firefox add-ons are written in Javascript and access document elements, just like Javascript scripts within HTML documents, except that the document an add-on accesses is named Chrome Document.

Accessing the Chrome Document

The Chrome document contains more than just the “window” element, accessed from a web page using Javascript. Chrome also contains menus, toolbars and other widgets. Let’s make changing one of the Chrome document’s elements your first step in add-on development. If you don’t have DOM Inspector installed in your browser, you can get it here. Now, you can use it to play around a little bit. For example, let’s change the ‘Tools’ menu’s name to ‘Fools’.

To do so, perform the following steps:

  1. Tools->Web Developer->DOM Inspector:
    StartDomInspector
  2. In the DOM Inspector menu bar, choose: File->Inspect Chrome Document->(tab name)
    InspectChromeDocument
  3. In the DOM Inspector Window, click the magnifying-glass icon.
    MagnifyingGlass
  4. In the browser’s window click ‘Tools’ menu
    IMPORTANT! This will NOT work if the “Global Menu BAR Integration” add-on is enabled!!!
  5. Open the DOM Inspector window.
    The ‘tools-menu’ node will appear on the right-hand part of the window.
    tools-menu

    Now, you can see that the value of the node’s “label” attribute is “Tools”
  6. Right click the “Label” attribute, then left-click “Edit”.
    clickEdit
  7. In the “Edit Attributes” window opened change the Node Value and click “OK”.
    editAttributes
  8. Nice work!!!
    niceWork

Congratulations! Now you know how to access chrome elements and modify them. This will help you later when you learn how to do it in Javascript.

Learn more about add-on development here.