Linux for Artists and Designers


• December 15, 2018 • Leave a Comment

I know a lot of Linux and software bloggers write often about the “Photoshop killers this” and the “best Linux/open source that” but I want to add my two cents as a long time Linux and open source user – early nineties to present – who does graphic design. I’m also not gaining financially to pump out those types of articles. I have been writing about this stuff before it was popular and my previous site here had a good following for Linux tutorials and free software listings, even though I’m not the best writer. 🙂 I switched to WordPress a few years ago and rarely update these days since the internet is flooded with similar content, but from time to time I like to think about what I’m doing and how I can share my experiences.

Over the many years I have done graphics I have worked on BeOS, Linux, Mac, and Windows. I have software all over the place for all four OSes. On Windows I think Adobe used to be the best option by far, not that their software was super amazing as you can make art in PaintBrush if you really want to, but rather for the plug-ins, brushes, and ease of use. I swicthed to OS X as my main OS for a few years only using Linux for programming. Of course I ran out and bought Photoshop 7 so I could have the best on Mac, but I lost interest because the software really never changed over the years. Sure, they move things around, make things easier, but honestly there wasn’t a huge change and the software does what it always did.

So my Macbook Pro was finally deemed too old for Apple to support so I decided, considering the apps in the App store are really not any better than their open source cousins I’ve used over the years, that their model isn’t really for me just like Microsoft years earlier. I honestly don’t want to spend $5k to $7k for a decent machine or be controlled by any corporation. Apple is now like Microsoft, maybe worse at this point. I decided to buy a powerful laptop with 16gb ram, fast solid state drives, 12 core i7 latest gen. CPU, and mid-range Nvidia, and best of all, a 17″ display. I ended up with a System 76 machine to support Linux even more and considering the cost to rent Adobe, which is unfortunate because CS6 is the best of the product line ever, I don’t think I’ll miss being billed to work and play.

Now you have a bit of background on me let’s get into my choice of Linux and desktop environment. I had the machine shipped with System 76’s Pop! OS, which is a tweaked Ubuntu 18.04 and Gnome 3. I hated it! The core, however, is solid and their drivers and driver support is tops. After giving LinuxMint, Deepin, and Manjaro a try I switched back to Pop and installed Budgie to make it more like OS X. I am not a fan of Gnome 3. Budgie gave me a little trouble but with a little tweaing myself I find it to be the best environment I’ve worked in for a while. Now that the OS is solid and secured it was time to install the software, and soon after I got a gig to do a bookcover, so away we go.

Inkscape
https://inkscape.org

For the bookcover I needed to create a scroll logo and graphic element. This choice was easy, Inkscape! I have nothing bad to say about Inkscape. It works and works well. For Vector work I have been using it on Windows, Mac, and Linux for years. It does the job of Adobe Illustrator so I never bought a copy. It is the most consistently good application in the open source world.

Gimp
https://www.gimp.org

Gimp worked well with a big image where Krita gave me some trouble. I paint in Krita at high res and had not had this problem before so it may be the latest version I used. I think Krita is as close to Photoshop as you’ll get in the opensource world and it is typically just fine, I won’t fault Krita, it’s really solid and under heavy development. Either way, Gimp did the job of adjusting the image to get it ready for print at 300dpi.

What you lose using these tools. Gimp is a bit of a learning curve from Photoshop, Krita not so much. The way I see it Gimp makes you work harder, or learn the non-automated way to get things done. If you need nice brushes and easier effects use Krita, if you don’t care either tool will do so pick the interface that suits you.

Plug-ins are basically non-existant. Gimp has a few really good plug-ins but finding them and finding versions that work with newer versions can be frustrating. This leads to my biggest complaint against open source, people create and abandon projects/web-sites often so unless you are willing to edit code you have to sometimes wait for others to find an interest in keeping things updated and available.

If you need Gimp plug-ins for versions < 2.8, some work on 2.10 for me, try the Gimp Plugin Registry archive (yes, it is dead as of this writing). Another option is to try other flavors. If you want Resynthisizer, G’Mic, etc. go here.

Other Gimp goodies, Gimp Paint Studio

For Windows users using Gimp 2.10: Gimp Extensions

Some updated plug-ins for Gimp 2.10 and G’Mic for Gimp and Krita

G’Mic
Multiple plug-ins
LayerFX

Scribus
https://www.scribus.net

I don’t do a lot of layout and for the little things I do I typically use LibreOffice Draw. For the book I found wrapping text painful in Draw so I installed the latest Scribus 1.5.5 SNV. It took me a day to figure it out, mainly wrapping text properly, but once I got it down I found this to be excellent software! I do not typically use PageMaker/InDesign so I cannot compare, but the software worked as expected and took only a day of learning and another half day to get everything put together. Book went to print and the customer was extremely happy. This tool will stay in my toolbox. I will admit I poked around for other layout programs for Linux. I was not thrilled with my findings, still you might want to try the alternatives.

I tried VivaDesigner. This is a commercial product and compared to the big boys the price was a bit high for a lower end alternative, strike one. The Linux installer was outdated and would not install on my machine, strike two. I installed the Windows version in Wine, seemed limited for a pay product, strike three.

I also tried Pagestream, another commercial offering. After installing a library it started right up but it seemed limited and dated. It could be a great product, I simply decided not to invest in learning it.

Scribus won simply because it’s full featured, not confusing, and free, but you do have options if Scribus isn’t what you want.

Business Side

Filezilla
https://filezilla-project.org

When all is said and done you need to get the product to the client. I use Filezilla as it’s the best FTP app IMO.

Now that the tools were picked and product has been delivered I’ll go into the administrative tools that I use that others fail to mention.

Kapow Time Tracking
https://gottcode.org/kapow

I like to track my time when I start working on a project so I can give detailed billing. This tool is one that I was going to write until I found Kapow. I was a little bummed it already existed. Oh well. This tool will track time on tasks in real-time. You could just write down start and end time but this is so convenient.

Planner
https://wiki.gnome.org/action/show/Apps/Planner?action=show&redirect=Planner

If you’re on larger/longer projects and/or working with teams Planner Project Management may be for you. I have it for this purpose to keep track of everything.

Osmo
http://clayo.org/osmo

Osmo is a nice personal task manager. It will keep you on track.

Mercurial-scm
https://www.mercurial-scm.org

For backups and revision I use Mercurial with TortoiseHG. Better safe than sorry.

Office, etc.

For invoicing I designed a simple template in LibreOffice and all other tools are stock Gnome/Ubuntu apps, like Geary for mail, Gnote, Gnome Calender, etc.

Misc.

Screen Ruler

In conclusion, I find this workflow to be just as powerful as the expensive alternatives, at least for me. If you do occasional freelance you cannot go wrong with these selections. The best part is that most are also available on Mac and Windows so if you’re not into Linux you can still use or try them freely.

Python3 Gtk3 Thread Example


• August 20, 2018 • Comments Off on Python3 Gtk3 Thread Example

Quick Python3 Gtk3 app to execute Python scripts to test long running threads in Gtk3 app. Some things could be better, like the python paths collection and displaying the PID, but I was focused on running threads without freezing the GUI and it just kind of happened. Hope it’s useful to someone.

#!/usr/bin/python3
import sys
if sys.version_info[0] < 3:
    raise Exception("Python 3 or a more recent version is required.")

if 'linux' not in sys.platform:
    raise Exception("Linux is required.")

try:
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk, Gio, GLib, GObject
except:
    raise Exception("Missing 'gi' [Gtk 3].")

try:
    import psutil
except:
    raise Exception("Missing 'psutil', try sudo apt install python3-psutil.")

import os
import os.path
import fnmatch
import pickle
import threading
import time
import getpass
from subprocess import PIPE
'''
Find all Python executables on Linux machine.
Allow easy execution of Python scripts from GUI,
because I'm lazy...
'''
GObject.threads_init() 

class Worker(threading.Thread):
    def __init__(self, cmd, callback):
        threading.Thread.__init__(self)
        self.cmd = cmd
        self.callback = callback

    def run(self):
        if not self.cmd:
            _get_execs() # Get Python execs.
            GObject.idle_add(self.callback)
        else:
            msg,err = _process(self.cmd)
            GObject.idle_add(self.callback,[msg,err])

def app_load():
    p = '/home/%s/.pyexec' % getpass.getuser()
    if not os.path.exists(p):
        os.mkdir(p)
    p = os.path.join(p,'execs.bin')
    with open(p, 'rb') as stream:
        data = stream.read()
        execs = pickle.loads(data)
    return execs

def update_execs(data):
    p = '/home/%s/.pyexec' % getpass.getuser()
    if not os.path.exists(p):
        os.mkdir(p)
    p = os.path.join(p,'execs.bin')
    with open(p, 'wb') as output:
        output.write(data)

def load_user():
    user = None
    p = '/home/%s/.pyexec/user.bin' % getpass.getuser()
    if os.path.exists(p):
        with open(p, 'rb') as stream:
            data = stream.read()
            user = pickle.loads(data)
    return user

def save_user(data):
    p = '/home/%s/.pyexec' % getpass.getuser()
    if not os.path.exists(p):
        os.mkdir(p)
    p = os.path.join(p,'user.bin')
    data = pickle.dumps(data)
    with open(p, 'wb') as output:
        output.write(data)

def search(where='/', find='python*[!-config]'):
    for dirpath, dirnames, filenames in os.walk(where):
        if 'flatpak' in dirpath.lower(): continue
        if 'timeshift' in dirpath.lower(): continue
        if 'bin' not in dirpath.lower(): continue
        for filename in filenames:
            file_path = os.path.join(dirpath, filename)
            if not os.access(file_path, os.X_OK): continue
            if not fnmatch.fnmatch(filename, find): continue
            if not os.path.islink(file_path): continue
            yield file_path

def _get_execs():
    python_execs = [item for item in search()]
    dumped = pickle.dumps(python_execs)
    update_execs(dumped)

def _process(cmd):
    proc = psutil.Popen(cmd, stdout=PIPE, stderr=PIPE)
    print('NAME: %s PID = %s' % (proc.name(), str(proc.pid).split()[0]))
    msg, err = proc.communicate()
    return msg, err

class Executor(Gtk.Window):
    '''
    Main app window class.
    '''
    def __init__(self):
        Gtk.Window.__init__(self, title="Python Executor")

        self.set_border_width(10)
        self.set_default_size(400, 350)
        self.python_list = None
        self.proj_path = None
        self.script = None
        self.selected = None
        self.cmd = None
        self.msg = ''
        self.err = ''
        self.pid = ''
        self.versions = ['/usr/bin/python'] # placeholder

        # If the python list does not exist create, else populate versions.
        self.app_load_check() 

        # Load user settings.
        self.proj_path_default = "/home/%s/Documents/Python" % getpass.getuser()
        self.script_default = "script.py"
        self.cbox_index = 0
        user_settings = load_user()
        if user_settings:
            self.cbox_index, self.proj_path_default, self.script_default = user_settings 

        # Define header add buttons.
        header = Gtk.HeaderBar(title="Python Executor")
        header.props.show_close_button = True
        self.set_titlebar(header)

        # Button to refresh python list.
        refresh_button = Gtk.Button()
        icon_refresh = Gio.ThemedIcon(name="reload")
        image_refresh = Gtk.Image.new_from_gicon(icon_refresh, Gtk.IconSize.BUTTON)
        refresh_button.add(image_refresh)
        refresh_button.set_tooltip_text("Refresh environments")
        refresh_button.connect("clicked", self.on_refresh_clicked)
        header.pack_start(refresh_button)

        # Kill button.
        kill_button = Gtk.Button()
        icon_kill = Gio.ThemedIcon(name="process-stop")
        image_kill = Gtk.Image.new_from_gicon(icon_kill, Gtk.IconSize.BUTTON)
        kill_button.add(image_kill)
        kill_button.set_tooltip_text("Kill Process")
        kill_button.connect("clicked", self.on_kill_clicked)
        header.pack_start(kill_button)

        # Execute button.
        run_button = Gtk.Button()
        icon_run = Gio.ThemedIcon(name="run-build")
        image_run = Gtk.Image.new_from_gicon(icon_run, Gtk.IconSize.BUTTON)
        run_button.add(image_run)
        run_button.set_tooltip_text("Run")
        run_button.connect("clicked", self.on_run_clicked)
        header.pack_start(run_button)

        # Define layout.
        self.box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10)
        self.pybox = Gtk.Box(spacing=10)
        self.prjbox = Gtk.Box(spacing=10)
        self.scrbox = Gtk.Box(spacing=10)

        self.add(self.box)

        # Python execs.
        py_label = Gtk.Label()
        py_label.set_text("Python")
        py_label.set_justify(Gtk.Justification.LEFT)
        py_label.set_hexpand(False)

        self.py_store = Gtk.ListStore(str)
        for ver in self.versions:
            if isinstance(ver, str):
                self.py_store.append([ver])

        self.python_list = Gtk.ComboBox.new_with_model(self.py_store)
        self.python_list.connect("changed", self.on_changed)
        self.python_list.set_hexpand(False)
        renderer_text = Gtk.CellRendererText()
        self.python_list.pack_start(renderer_text, True)
        self.python_list.add_attribute(renderer_text, "text", 0)
        self.python_list.set_active(self.cbox_index) 

        self.pybox.pack_start(py_label, False, False, 0)
        self.pybox.pack_end(self.python_list, False, True, 0)
        self.box.pack_start(self.pybox, False, True, 0)

        # Project Path.
        prj_label = Gtk.Label()
        prj_label.set_text("Project ")
        prj_label.set_justify(Gtk.Justification.LEFT)
        prj_label.set_hexpand(False)

        self.proj_path = Gtk.Entry()
        self.proj_path.set_text(self.proj_path_default )
        self.proj_path.set_hexpand(True)

        self.prjbox.pack_start(prj_label, False, True, 0)
        self.prjbox.pack_end(self.proj_path, False, True, 0)
        self.box.pack_start(self.prjbox, False, True, 0)

        # Script
        scr_label = Gtk.Label()
        scr_label.set_text("Script   ")
        scr_label.set_justify(Gtk.Justification.LEFT)
        scr_label.set_hexpand(False)

        self.script = Gtk.Entry()
        self.script.set_text(self.script_default)
        self.script.set_hexpand(True)

        self.scrbox.pack_start(scr_label, False, True, 0)
        self.scrbox.pack_end(self.script, False, True, 0)
        self.box.pack_start(self.scrbox, False, True, 0)

        # Message area.
        scrolledwindow = Gtk.ScrolledWindow()
        scrolledwindow.set_hexpand(True)
        scrolledwindow.set_vexpand(True)

        self.message_view = Gtk.TextView()
        self.textbuffer = self.message_view.get_buffer()
        self.tag_err = self.textbuffer.create_tag('err', foreground="#FF0000")
        self.tag_msg = self.textbuffer.create_tag('msg', foreground="#FFFFFF")
        scrolledwindow.add(self.message_view) 
        self.box.pack_start(scrolledwindow, True, True, 0)

        self.show_all()

    def app_load_check(self):
        '''Fetch Python paths.'''
        p = '/home/%s/.pyexec' % getpass.getuser()
        if not os.path.exists(p):
            os.mkdir(p)
        p = os.path.join(p,'execs.bin')
        if not os.path.exists(p):
            thread = Worker(None, self.end_refresh)
            thread.start()
        else:
            self.versions = app_load()

    def on_refresh_clicked(self, widget):
        '''Refresh Python paths.'''
        thread = Worker(None, self.end_refresh)
        thread.start()

    def end_refresh(self):
        '''Thread callback.'''
        self.versions = app_load()
        for ver in self.versions:
            if ver not in self.py_store:
                if isinstance(ver, str):
                    self.py_store.append([ver])

    def on_changed(self, widget):
        '''Selected Python path.'''
        index = widget.get_active() 
        self.selected = widget.get_model()[index][0]

    def on_kill_clicked(self, widget):
        kill_msg = '\n* kill: Nothing to do.'
        end_iter = self.textbuffer.get_end_iter()
        for process in psutil.process_iter():
            if process.cmdline() == self.cmd:
                process.terminate()
                kill_msg = '\n* %s: %s killed' % (process.pid, process.cmdline())
                self.textbuffer.insert(end_iter, kill_msg)
                break

    def on_run_clicked(self, widget):
        '''Execute Python script.'''
        ok = True
        self.cmd = None
        python_path = self.selected
        python_path_id = self.python_list.get_active()

        if not python_path:
            ok = False
            self.textbuffer.set_text('Python exec not defined.')
            
        if not os.path.exists(python_path):
            ok = False
            self.textbuffer.set_text('Python exec not found: %s' % python_path)

        script_path = self.proj_path.get_text()
        script = self.script.get_text()  

        full_script_path = os.path.join(script_path,script)
        if not os.path.exists(full_script_path):
            ok = False
            self.textbuffer.set_text('Script not found: %s' % full_script_path)
        
        if ok:

            user_set = [python_path_id, script_path, script]
            save_user(user_set)

            self.textbuffer.set_text(self.pid)
            
            self.pid = 'PID: Unkown. Possibly ended quickly.'
            self.cmd = [python_path, full_script_path]

            thread = Worker(self.cmd, self.messages)
            thread.start()
            
            for process in psutil.process_iter():
                if process.cmdline() == self.cmd:
                    self.pid = 'PID = %s: %s' % (process.pid, process.cmdline())
                    self.textbuffer.set_text(self.pid)
                    break

    def messages(self,rvals):
        r_err = rvals[-1].decode()
        r_ok = rvals[0].decode()

        self.err = '\nResults:\n\n%s' % r_err
        self.msg = '\nResults:\n\n%s' % r_ok

        start_iter = self.textbuffer.get_start_iter()
        end_iter = self.textbuffer.get_end_iter()
        self.textbuffer.remove_all_tags(start_iter,end_iter)
        if r_err: 
            self.textbuffer.insert_with_tags(end_iter, self.err, self.tag_err)
        elif r_ok: 
            if 'exception' in r_ok.lower() or 'error' in r_ok.lower() and 'traceback' in r_ok.lower():
                self.textbuffer.insert_with_tags(end_iter, self.msg, self.tag_err)
            else:
                self.textbuffer.insert_with_tags(end_iter, self.msg, self.tag_msg)
        self.message_view.show()

if __name__ == '__main__':
    win = Executor()
    win.connect("destroy", Gtk.main_quit)
    win.show_all()
    Gtk.main()

Create mov,mp4 thumbnails from Python3


• July 31, 2018 • Comments Off on Create mov,mp4 thumbnails from Python3

I was working on a Gtk 3 project to roll up all my iPhone videos into a flowbox for easy locating and processing since iPhone doesn’t name things in a meaningful way and photo managers dump things into not so meaningful folders, thumbnails was a must to locate videos easily. Plus, I wanted to do some Gtk programming.

I started with GStreamer 1.0, which worked, but not for .mov files. This handles MP4 and MOV. I have not tested other types so it might need further tweaks.

Hope it is helpful to someone. I can provide GStreamer code if you need it. It is also Python and is slightly faster.

#!/usr/bin/python3
import os
import time
import datetime
import getpass
import cv2
from PIL import Image

"""
Requires:
    OpenCV2 
    PIL

Install via pip or apt.
"""


def get_framecv(in_vid, out_vid, w=192, h=108):
    """Generate thumbnail."""
    # Opencv create thumb.
    try:
        cap = cv2.VideoCapture(in_vid)
        video_length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - 1
        print('length',video_length)
        while cap.isOpened():
            try:
                ret, frame = cap.read()
                cv2.imwrite(out_vid, frame)
                break
            except:
                pass
        cap.release()
        # PIL: resize
        img = Image.open(out_vid) # image extension *.png,*.jpg
        img = img.resize((w, h), Image.ANTIALIAS)
        img.save(out_vid)
    except Exception as e:
        return e

def is_video_file(filename, extensions):
    """Filter videos"""
    return any(filename.lower().endswith(e) for e in extensions)

def scan_vids(base_dir, extensions):
    """Walk path and get all videos in path."""
    for dirpath, dirs, files in os.walk(base_dir):
        for filename in files:
            if is_video_file(filename, extensions):
                full_path = os.path.join(dirpath,filename)
                date_object = datetime.datetime.fromtimestamp(os.path.getctime(full_path))
                yield os.path.join(dirpath,filename),date_object.date()

def gen_thumbs(path,extensions,output=None):
    """Worker function"""
    img_date = datetime.datetime.now().date()
    associations = []

    if output:
        img_store = output
    else:
        #img_store = r'/home/%s/video_thumbs' % getpass.getuser()
        img_store = os.path.join(path, 'thumbnails')

    if not os.path.exists(img_store):
        os.mkdir(img_store)

    for vid_info in scan_vids(path, extensions):
        vid_path,vid_date = vid_info
        vid_name = os.path.split(vid_path)[-1].split('.')[0]
        img_path = os.path.join(img_store,'thumb_%s.png' % vid_name)
        err = get_framecv(vid_path,img_path)

        if err:
            continue # Handle errors.

        associations.append((img_path, img_date, vid_path, vid_date))

    return associations


if __name__ == '__main__':

    filter_extensions = ['.mov', '.mp4']
    local_path = None # Set path to run from program.

    if local_path:
        user_path = local_path
    else:
        # Run from terminal.
        user_path = None

        user_path = input('Path to videos: ')

    if not user_path:
        print('Path required.')
        os._exit(0)
    if not os.path.exists(user_path):
        print('Supplied path %s is invalid.' % user_path)
        os._exit(0)

    # Run...
    results = gen_thumbs(user_path, filter_extensions, output=None)
    # Print results.
    for i in results: print(i)

GTK3 Calendar dialog example in Python.


• July 23, 2018 • Comments Off on GTK3 Calendar dialog example in Python.

 

#!/usr/bin/python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GObject
GObject.threads_init()

class CalDialog(Gtk.Dialog):
    '''
    Calendar Dialog
    '''
    def __init__(self, parent):
        Gtk.Dialog.__init__(self, "Select Date", parent, 0,
            (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
             Gtk.STOCK_OK, Gtk.ResponseType.OK))

        self.set_default_size(300, 200)

        self.value = None

        box = self.get_content_area()

        calendar = Gtk.Calendar()
        calendar.set_detail_height_rows(1)
        calendar.set_property("show-details",True)
        calendar.set_detail_func(self.cal_entry)

        box.add(calendar)

        self.show_all()

    def cal_entry(self, calendar, year, month, date):
        #print(year, month, date)
        self.value = calendar.get_date()

class FlowBoxWindow(Gtk.Window):
    '''
    Flowbox example mixed with HeaderBar from
    https://python-gtk-3-tutorial.readthedocs.io/en/latest/introduction.html
    '''
    def __init__(self):
        Gtk.Window.__init__(self, title="Calendar Demo")
        self.flowbox = None
        self.set_border_width(10)
        self.set_default_size(400, 250)

        header = Gtk.HeaderBar(title="Calendar Demo")
        header.props.show_close_button = True

        # Add button to header to display calendar dialog.
        cal_button = Gtk.Button()
        icon_cal = Gio.ThemedIcon(name="gnome-calendar")
        image_cal = Gtk.Image.new_from_gicon(icon_cal, Gtk.IconSize.BUTTON)
        cal_button.add(image_cal)
        cal_button.set_tooltip_text("Pick date")
        cal_button.connect("clicked", self.on_cal_clicked)
        header.pack_start(cal_button)

        # Button to exit main window.
        exit_button = Gtk.Button()
        icon_exit = Gio.ThemedIcon(name="exit")
        image_exit = Gtk.Image.new_from_gicon(icon_exit, Gtk.IconSize.BUTTON)
        exit_button.add(image_exit)
        exit_button.set_tooltip_text("Exit")
        exit_button.connect("clicked", self.on_exit_clicked)
        header.pack_start(exit_button)

        self.set_titlebar(header)

        self.flowbox = Gtk.FlowBox()
        self.flowbox.set_valign(Gtk.Align.START)
        self.flowbox.set_max_children_per_line(30)
        self.flowbox.set_selection_mode(Gtk.SelectionMode.NONE)
        self.flowbox.set_property("vexpand", False)

        self.show_all()

    def on_cal_clicked(self, widget):
        # Open calender and get user selection,
        dialog = CalDialog(self)
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            print(dialog.value) # See terminal.
        # Close calendar.
        dialog.destroy()

    def on_exit_clicked(self, widget):
        self.destroy()

win = FlowBoxWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

System 76 Oryx Pro Host Virtualization


• July 10, 2018 • Comments Off on System 76 Oryx Pro Host Virtualization

Preview of OS X and Windows 10 virtualized on a June 2018 Oryx Pro laptop.


1920×1080 MP4

Brightness fix on System 76 Oryx Pro


• July 8, 2018 • Comments Off on Brightness fix on System 76 Oryx Pro

I recently received the System 76 Oryx Pro laptop – June 2018 – and this thing is a beast. If you want more portable go with something else. I decided to get it preinstalled with Pop! OS to see how well it integrated with the hardware. By default most things worked and I really didn’t spend much time configuring or fixing things beyond setting it up for me and my workflow. I did install Gnome Tweaks to alter a couple of things but for the most part the OS is unchanged.

To the problem. Out of the box there was no ability to control brightness on the laptop monitor. I do not use external monitors so I do not know if this will fix anything related to that. To partially fix brightness when using Nvidia in Pop! OS I simply flashed the BIOs and it magically started working. The brightness controls/keys worked in Pop but it stops working after the lid is closed or the machine goes to sleep. This did not work for Nvidia in Mint 19 at all.

Update: The following grub hack does not work! None do, unless you want to install utils and write some scripts to hack things. What I found that does work is to install Linux Mint 19, much nicer OS IMO but this likely works in any Gnome DE, and install this. The control in power settings wont work, but this does and adds color too, but only if you switch to Intel drivers. I assume Intel will work better in Pop too. I also had problems with the System 76 drivers in Mint so install at your own risk. I’m hoping a future Nvidia driver/kernel update will correct the problem at some point.

If you plan to install Windows this laptop is a rebranded Sager Gaming laptop so visit their site for ease of driver lookups. I think it’s a Clevo P650SE.

The second problem was after putting the laptop to sleep/suspend (closing the lid) the brightness controls would stop working until it was rebooted. Irritating! Here’s the fix:

1. Verify the Nvidia driver is installed and in use.
2. Update BIOs firmware if screen brightness slider missing and keyboard keys are not working.
3. Edit the /etc/default/grub file from the terminal.
a. sudo nano /etc/default/grub
b. Change GRUB_CMDLINE_LINUX_DEFAULT from “quiet splash” to “quiet splash acpi_osi=Linux”
c. sudo update-grub
d.reboot

Apple is a shit hole company


• August 22, 2017 • Comments Off on Apple is a shit hole company

I went to upgrade to El Capitan on my MacBook Pro (17-inch, Mid 2009). I added max ram and a solid state drive. I have no problems virtualizing Windows and Linux on this fucker, but Apple decided my 17″ MBP is no longer viable and will not let me upgrade. Yes, I know I can without them, but fuck that! This is outright bullshit! So I went to run XCode, which I hadn’t ran since the last update – I develop more in Windows or Linux in Python or Rust than OS X in XCode – and they broke it. So I go to the AppBore to upgrade and it just spins, so I am not allowed to update XCode either? I am now forced to hack Sierra onto the machine, install Linux and virtualize OS X, or buy a new laptop with a smaller fucking screen. FUCK YOU! I am buying a System76 powerhouse, and maybe a Puri.sm with the money I save, and virtualizing their crap. Either way, I wrote my two cents on the AppStore and of course they will not allow it to go through so here it is:

“I cannot update XCode, because Apple decided that the over priced hardware I purchased, that was 6 months behind other companies when it was new, is not viable for an OS upgrade from El Capitan to Sierra. I run Windows and Linux virtualized on this laptop as well as play games with no issue. Not only that but they broke the XCode I currently have installed, which worked fine until the last update. The reality, the company changes your system preferences without permission, the majority of AppStore apps are horrid, they kill apps in the store often or steal the ideas effectively killing the original app, and ask for way more for older hardware than required to blackmail you into buying new hardware just to run a single OS version above what you’re running already. They are not a small company that needs to command a higher cost to maintain their business or need to fill landfills with viable hardware to keep money rolling in. The iPhone is great but as a company they are worse than Microsoft in the nineties. I’m going to System76 and LinuxMint and I will virtualize OS X from now on. Not worth my time or money anymore…”

Now don’t give me that, “they are protecting you”, “they want to be secure”, “they need to advance” bullshit. If the motherfuckers are using open Unix shit to build off of, don’t fuck it up, don’t mess with my settings, allow good programs into the AppStore, allow Linux and/or open devs a good environment to build in, and stop trying to be an everything greedy business. If Windows was better I’d go back to that as Microsoft has at least wised up a little bit.

Really nice set of free javascript canvas gauges.


• February 5, 2017 • Comments Off on Really nice set of free javascript canvas gauges.

https://canvas-gauges.com

Krita is becoming a Painter and Photoshop killer.


• January 9, 2017 • Comments Off on Krita is becoming a Painter and Photoshop killer.

It has been a long time since I checked out Krita. I Painted this in Krita 3.1.1 on Mac Yosemite, versions for Windows as well and of course Linux; all are free. The bird took about six hours, give or take, and the program was not shut down for two days. I had one lock up during export of the final PNG save, no problems with the tools or app other than that. Be sure to save often, just in case. I used the following brushes, available here:

David Revoy
Concept Art & Illustration Pack
Cazu Brush Collection
Raghukamath

Just playing around I created this in no time:
Background
Further playing ended with this:
Background
Of course this gave me an excuse to continue painting:
Background
and finally, the end result:
Background

Linux like Package Management for Windows and Mac


• January 8, 2017 • Comments Off on Linux like Package Management for Windows and Mac

Package managers for installing open software. These gives you Linux like package management similar to Linux apt, zypper, yum, etc…

Windows:

https://chocolatey.org/install

Mac:

http://brew.sh/

Brew GUI

https://www.cakebrew.com/