our secret dating chat

full hookup campgrounds in indiana

Pipewire comes with a native module to send audio output to all connected audio devices. This is done by creating a combined output sink using module-combine-stream in Pipewire config. This is ideal if you have multiple Bluetooth headsets or speakers and want to output same audio to all of them at the same time.

The following instructions are tested on Debian 12 (Bookwork) using Gnome. They should work on other Debian based distros i.e. Ubuntu, Mint

The basic steps are as follows:

  • Open /usr/share/pipewire/pipewire.conf
  • Find context.modules section and add a module block for libpipewire-module-combine-stream
  • Restart Pipewire
# Open pipewire.conf
sudo nano /usr/share/pipewire/pipewire.conf

# Add module-combine-stream to context.modules block. 
context.modules = [
{   name = libpipewire-module-combine-stream
    args = {
        combine.mode = sink
        node.name = "my_combined_sink"
        node.description = "My Combined Sink"
        combine.props = {
            audio.position = [ FL FR ]
        stream.rules = [
                matches = [
                        media.class = "Audio/Sink"
                actions = {
                    create-stream = {

# Restart Pipewire
systemctl --user restart pipewire pipewire-pulse

Once restarted, “All Connected Outputs” will appear in Top Panel and Sound Settings

Never buy a Baseus product

UPDATE: I guess this post reached someone higher up at Baseus and I got the following message:

I have agreed to take the replacement and refund, but the blog post stays with this update.

tl;dr: Baseus does not honor any warranty claims and resorts to shady tactics to avoid accountability. This applies to their official store and authorized sellers.

Save your time and money, do not buy Baseus Products.

Baseus is a Chinese lifestyle brand that makes some good products and does great marketing for those products. I was impressed with their 120w GaN charger, as it would mean I will have less charging bricks to deal with and plug in to the wall socket. The charger looked good, had good reviews and came with a 1 year warranty (this point is very important), so I pulled the trigger and purchased it from their official store on AliExpress in November 2020. It got delivered early December 2020.

Fast Forward to May 2021 (5 months later), my laptop which was plugged into the Baseus 120w GaN charger stopped charging and I got a strong burning smell coming from the charger. I immediately unplugged it. My charger was dead and my string of misfortunes with Baseus began.

I contacted the “Official” Baseus store on AliExpress where I bought the charger and requested a replacement as the charger was still under warranty. The response I got was that they can “give some discount on the next order”.

The response from the store didn’t sit well with me so I went to Baseus Support website (https://support.baseus.com) and started a warranty claim process. After waiting a few days I finally got a response.

Okay. Baseus support basically told me to contact the store on AliExpress which has already refused to honor the warranty claim and offered me a discount on my next purchase, which is not acceptable. I replied with the screenshot of the conversation on AliExpress, and informed the Baseus support team that the seller is refusing to honor the warranty.

At this point I was hoping they would see that I have exhausted the option of contacting the seller directly and I am reaching out to the official support team to provide a reasonable solution i.e. honor the warranty. Sadly I was in for more disappointment.

Clearly something was amiss. I thought I had ordered from the official Baseus store on AliExpress. So I went to double check on the Baseus support warranty page (https://support.baseus.com/warranty.html). Sure enough, the “BASEUS Officialflagship Store” is listed as an official store on AliExpress.

I replied back with the above screenshot and got the following response.

At this point, I gave up on “Official” Baseus support and sent the following reply, pointing out that Baseus is supposed to hold their authorized sellers accountable, instead of shifting blame.

As a last resort, I contacted the AliExpress seller again to point out that they are the authorized seller as per official Baseus support and responsible for after-sales service and honoring the warranty.

This time they made up a new excuse, saying they only offer 2 months warranty and cannot help me. Sorry Baseus, you are not seeing another cent from me.

Finally I gave up and decided to write up this post to warn others who are considering Baseus products.

Save your time and money, do not buy Baseus products. They will lie, shift blame and ultimately leave you with a broken product and promise.

Properly Configure Nginx alias directive with PHP

When using alias directive, the SCRIPT_FILENAME parameter passed onto FastCGI interpreter should be $request_filename instead of the default $fastcgi_script_name. This ensures that the PHP interpreter receives the correct file path and does not return 404 Not Found.

Example Code:

   location /myalias {
      alias /path/to/alias;
      location ~ \.php$ {
         fastcgi_pass fastcgi_backend;
         include fastcgi_params;
         fastcgi_param SCRIPT_FILENAME $request_filename;

Keyword based inline Search and Replace with sed

sed is a nifty utility that allows you to search and replace text in a file using a short 1-liner.

The following command does the following:
1. Searches for the keyword in every line of the input_file
2. In every matching line it looks for search_string
3. It replaces every instance of search_string with replace_string

sed '/keyword/s/search_string/replace_string/g' input_file



Bluetooth Audio Receiver / A2DP Sink with Raspberry Pi

After much trial and error, I have managed to configure Raspberry Pi to function as a Bluetooth Audio Receiver, also known as A2DP Sink mode.

Much of the articles and configurations on the web are for older version of Debian (<=7.x) which worked correctly with older versions of PulseAudio (<=4.x), Alsa & Bluez (<=4.x).

The following configuration has been tested with latest release of Xbian, which is based on Debian Jessie (8.0) and Raspberry Pi 3, which comes with a built-in bluetooth module. Other compatible bluetooth modules should work as well. Continue reading Bluetooth Audio Receiver / A2DP Sink with Raspberry Pi

How to search and replace with nano text editor

Nano is a very compact and feature packed text editor commonly found on Linux and Unix based OS. One of the lesser used feature that is very useful is search & replace.

To Search and Replace text in the currently open file:

Press Ctrl + \
Enter your search string [return]
Enter your replacement string [return]
Press A to replace all instances

The search string can also be a regular expression.

Port Forwarding in Mikrotik RouterOS

Ports can be opened/forwarded in Mikrotik RouterOS using the snippet below.

/ip firewall nat add chain=dstnat dst-port=1234 action=dst-nat protocol=tcp to-address= to-port=1234

Note the following parameters and edit as necessary:

  • dst-port
  • to-port
  • to-address
  • protocol

Introduction to hashing passwords in PHP (5.5+)

Every PHP developer at some point has a need for restricting access to certain parts of their web application and allow users to pass through secure areas with a username and password.

Due to it’s long history, PHP has a lot of practices around security which are no longer secure, or appropriate for the application requirements these days. Among such practices is hashing and securing passwords using algorithms such as MD5, SHA1, etc.

Securing passwords with md5, SHA1, SHA256 or custom hash generators is considered bad practice these days. According to PHP.net

Hashing algorithms such as MD5, SHA1 and SHA256 are designed to be very fast and efficient. With modern techniques and computer equipment, it has become trivial to “brute force” the output of these algorithms, in order to determine the original input.

Because of how quickly a modern computer can “reverse” these hashing algorithms, many security professionals strongly suggest against their use for password hashing.

The methods considered secure a few years ago, are now obsolete/insecure due to ever increasing computing power and advanced techniques. And unless you are well versed in the area of cryptography and security, it is never a good idea to roll your own security mechanisms.

The current best practice is to use the native password hashing API, introduced in PHP version 5.5. The API provides two useful functions, namely password_hash and password_verify.

password_hash() creates a new password hash using a strong one-way hashing algorithm.

password_verify() verifies that the given hash matches the given password.

Using these functions is fairly straightforward. See the following example.


$hash = password_hash('valid_password', PASSWORD_DEFAULT);

if (password_verify('invalid_password', $hash)) {
    // Correct Password
} else {
    // Wrong password

password_hash() currently provides Blowfish algorithm for creating the hash, and it is set as the default algorithm. The PASSWORD_DEFAULT constant is currently set to use the Blowfish algorithm. However, you may specify the Blowfish algorithm explicitly using the PASSWORD_BCRYPT constant, if the requirement is to always use Blowfish. Note that the password_verify() function is forward compatible, therefore PASSWORD_DEFAULT is the preferred option as it will provide the best possible hashing mechanism as PHP updates in future, while still working with previously generated hashes.

Blowfish allows specifying the cost of generating the hash. The cost of the hash implies the complexity and the processing power required to generate the hash. The higher the cost, the more complex the hash, the more processing power and time required to generate the hash. Depending on the use case of the application, and the required security complexity, the cost can be specified. The default cost of the Blowfish algorithm used in password_hash function is 10.

The generated hash is made up of algorithm, cost and salt as part of the returned hash. This eliminates the need to separately generate and store random salt values, and according to PHP.net it is considered simplest and most secure approach.

See the following pages to get up to speed with native Password Hashing API in PHP


  1. I have corrected the article to reflect the point made by /u/LawnGnome on reddit about hashes being forward compatible, this it is preferred to use PASSWORD_DEFAULT for algorithm.
  2. password_compat library provides the password_* functions for PHP >= 5.3.7. https://github.com/ircmaxell/password_compat – Thanks /u/PolarZoe
  3. Updated Blowfish constant to PASSWORD_BCRYPT, in line with native hashing API.

Simpler Role Based Authorization in Yii 2.0

UPDATE: Starting with version 2.0.2, Yii2 Advanced Template does not contain “role” column in the User table by default. Before proceeding to the tutorial below, do the following:

  1. Create a column called role in the user table.
  2. Update the User model by adding the role attribute and updating the User class docblock accordingly.

Yii 2.0 has a built in Access Control that supports 2 roles out of the box to check whether the user is a guest or if the user is logged in. Sometimes there is a need to simply extend the Access Control Layer with few more roles to distinguish the logged in users i.e. admin, moderator, without the full blown RBAC graph with permissions, roles and role assignments that Yii provides.

In this post, I will show how to implement simple Role Based authorization by simply extending the AccessRule class that defines the default rules and overriding the matchRule() function call, which will provide the additional rule matching logic. Continue reading Simpler Role Based Authorization in Yii 2.0

UDP Chat in Python Using Socket

Here I will share a very basic UDP chat application in Python using sockets.

It can work in point-to-point or broadcast mode.

For Point-to-Point, enter IP and Port.

For Broadcasting mode set the last byte of IP address to 255. i.e.

Port number is HEX, remove the base 16 to make it decimal.

#!/usr/bin/env python
import socket
import sys, select
# Read a line. Using select for non blocking reading of sys.stdin
def getLine():
    i,o,e = select.select([sys.stdin],[],[],0.0001)
    for s in i:
        if s == sys.stdin:
            input = sys.stdin.readline()
            return input
    return False
host = raw_input("Please Enter IP: ")
port = int(raw_input("Please Enter PORT: "), 16) # Base 16 for hex value
send_address = (host, port) # Set the address to send to
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    # Create Datagram Socket (UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # Make Socket Reusable
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Allow incoming broadcasts
s.setblocking(False) # Set socket to non-blocking mode
s.bind(('', port)) #Accept Connections on port
print "Accepting connections on port", hex(port)
while 1:
        message, address = s.recvfrom(8192) # Buffer size is 8192. Change as needed.
        if message:
            print address, "> ", message
    input = getLine();
    if(input != False):
        s.sendto(input, send_address)